python tornado下载远程文件

He *_*ang 0 python tornado download

我想下载一个远程文件并提供文件名.如果文件在我们的服务器上,则此方法有效.但它不适用于远程文件和下载somerandomname.pdf

<a href="http://file.com/somerandomname.pdf" download="mypdf.pdf">DOWNLOAD</a>
Run Code Online (Sandbox Code Playgroud)

现在我尝试在python处理程序中下载它.它工作并下载我想要的文件名.但问题是我只能在浏览器中看到下载的文件util已完成下载.我无法在浏览器中看到下载过程.它只是在后端加载远程文件.有没有办法来解决这个问题?

def get(self):
    url = self.get_argument('url')
    filename = self.get_argument('filename')
    self.set_header('Content-Type', 'application/octet-stream')
    self.set_header('Content-Disposition', 'attachment; filename=%s' % filename)
    f = urllib2.urlopen(url)
    self.write(f.read())
    self.finish()
Run Code Online (Sandbox Code Playgroud)

Ben*_*ell 5

  1. 你打电话后不会发送标题set_header(); 它们不会被发送,直到您调用flush()finish()(除其他外,如果在调用之前引发异常,则可以使用错误页面替换输出flush())

  2. 即使您打电话flush(),整个服务器在通话期间也会被阻止urlopen().这是一个阻塞调用,必须用Tornado中的异步版本替换(有关详细信息,请参阅用户指南).Tornado提供了一个异步HTTP客户端,可用于代替urlopen():

    @gen.coroutine
    def get(self):
        url = self.get_argument('url')
        filename = self.get_argument('filename')
        self.set_header('Content-Type', 'application/octet-stream')
        self.set_header('Content-Disposition', 'attachment; filename=%s' % filename)
    
        self.flush()
        response = yield AsyncHTTPClient().fetch(url)
        self.finish(response.body)
    
    Run Code Online (Sandbox Code Playgroud)
  3. 此过程一次将整个远程文件加载到内存中,并且在从远程服务器读取整个文件之前不会将任何文件发送到浏览器.如果文件很大,您可能希望以块的形式读取它并在读取它们时将它们发送回客户端:

    # inside get() as above, after self.flush():
    def streaming_callback(chunk):
        self.write(chunk)
        self.flush()
    yield AsyncHTTPClient().fetch(url, streaming_callback=streaming_callback)
    self.finish()
    
    Run Code Online (Sandbox Code Playgroud)