Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/320.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
用于下载的从FTP服务器到Flask服务器的Python流_Python_Flask_Ftp_Ftplib - Fatal编程技术网

用于下载的从FTP服务器到Flask服务器的Python流

用于下载的从FTP服务器到Flask服务器的Python流,python,flask,ftp,ftplib,Python,Flask,Ftp,Ftplib,我有一个Python Flask应用程序,可以从远程FTP服务器获取下载文件的请求。我使用BytesIO保存从FTP服务器下载的文件内容,使用retrbinary: import os from flask import Flask, request, send_file from ftplib import FTP from io import BytesIO app = Flask(__name__) @app.route('/') def hello_world(): ret

我有一个Python Flask应用程序,可以从远程FTP服务器获取下载文件的请求。我使用
BytesIO
保存从FTP服务器下载的文件内容,使用
retrbinary

import os

from flask import Flask, request, send_file
from ftplib import FTP
from io import BytesIO

app = Flask(__name__)

@app.route('/')
def hello_world():
    return 'Hello, World!'

@app.route('/download_content', methods=['GET'])
def download_content():
    filepath = request.args.get("filepath").strip()
    f = FTP(my_server)
    f.login(my_username, my_password)
    b = BytesIO()
    f.retrbinary("RETR " + filepath, b.write)
    b.seek(0)
    return send_file(b, attachment_filename=os.path.basename(filepath))

app.run("localhost", port=8080)
这里的问题是,当点击
download_content
路径时,首先文件的内容进入
BytesIO
对象,然后发送到前端进行下载

从FTP服务器下载文件时,如何将文件流式传输到前端?我迫不及待地等待文件在
BytesIO
对象中完全下载,然后执行
send\u file
,因为这既可能导致内存效率低下,也可能导致时间消耗


我已经读过Flask的
send_文件
接受
生成器
对象,但是如何使
BytesIO
对象成批地到
send_文件

看起来您需要设置一个工作线程来管理从
retrbinary

由于我们遇到了同样的问题,我已经为这一点做了一个快速的要点。这种方法似乎有效

可能应该添加一些超时和逻辑来处理连接超时ect,但这是基本形式

解释 队列不保证工作进程
getBytes
为空时已完成,因此必须有一个信号量/事件来指示生成器
sendBytes
工作进程何时完成。但是,在设置完成之前,我必须等待队列中的所有块首先被处理,因此必须执行
self.bytes.join()

如果有人能想出更优雅的方法,我很感兴趣

class FTPDownloader(object):
  def __init__(self, host, user, password, timeout=0.01):
    self.ftp = FTP(host)
    self.ftp.login(user, password)
    self.timeout = timeout

  def getBytes(self, filename):
    print("getBytes")
    self.ftp.retrbinary("RETR {}".format(filename) , self.bytes.put)
    self.bytes.join()   # wait for all blocks in the queue to be processed
    self.finished.set() # mark streaming as finished

  def sendBytes(self):
    while not self.finished.is_set():
      try:
        yield self.bytes.get(timeout=self.timeout)
          self.bytes.task_done()
      except Empty:
        self.finished.wait(self.timeout)
    self.worker.join()

  def download(self, filename):
    self.bytes = Queue()
    self.finished = Event()
    self.worker = Thread(target=self.getBytes, args=(filename,))
    self.worker.start()
    return self.sendBytes()