2015-12-17 5 views
0

Я хочу загрузить удаленный файл и указать имя файла. Этот метод работает, если файл находится на нашем сервере. Но это не работает для удаленного файла и загрузить в somerandomname.pdfpython tornado загрузить удаленный файл

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

Теперь я попытался в обработчике питона, чтобы загрузить его. Он работает и загружает имя файла, которое я хочу. Но проблема в том, что я могу видеть только загруженный файл, если загрузка завершена в браузере. Я не вижу процесс загрузки в браузере. Это просто загрузка удаленного файла в бэкэнд. Есть ли способ исправить это?

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() 
+0

Как я понимаю, вы хотите, чтобы прокси-файл? Покажите своего обработчика – kwarunek

+0

@kwarunek Да, ур. Я обновил свой обработчик. Похоже, он застрял в f.read(), чтобы загрузить файл. Я также попробовал AsynHTTPClient.fetch(), но они такие же. Почему браузер не показывает процесс загрузки, я уже отправляю заголовок перед чтением файла? –

ответ

5
  1. Заголовки не посылаются, как только вы звоните set_header(); они не отправляются, пока вы не вызовете flush() или finish() (между прочим, это то, что делает возможным заменить выход с страницы ошибки, если возникает исключение перед вызовом flush())

  2. Даже если вы звоните flush() , весь сервер блокируется во время вызова до urlopen(). Это блокирующий вызов, который должен быть заменен асинхронной версией в Tornado (подробнее об этом см. В файле user's guide). Торнадо обеспечивает асинхронный клиент 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) 
    
  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() 
    
+0

Спасибо. Ты спасаешь мой день! Последнее, что я получил ошибку таймаута для AsyncHTTPClient(). Fetch, если файл слишком велик. Могу ли я установить тайм-аут в клиенте? –

+0

Спасибо. Я выяснил вопрос о тайм-ауте –

Смежные вопросы