python tornado下载远程文件

时间:2015-12-17 06:53:06

标签: python download tornado

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

<a href="http://file.com/somerandomname.pdf" download="mypdf.pdf">DOWNLOAD</a>

现在我尝试在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()

1 个答案:

答案 0 :(得分:5)

  1. 拨打set_header()后,不会发送标题;在调用flush()finish()之前不会发送它们(除此之外,如果在调用{{1}之前引发异常,则可以使用错误页面替换输出})

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

    urlopen()
  3. 此过程会立即将整个远程文件加载到内存中,并且在从远程服务器读取整个文件之前不会将任何远程文件发送到浏览器。如果文件很大,您可能希望以块的形式阅读它并在阅读时将它们发送回客户端:

    @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)