Разница между Wget иquests.get в отношении загрузки файла - PullRequest
0 голосов
/ 27 апреля 2018

У меня странная ошибка. На Dropbox есть файл, который я загружаю со следующим кодом Python:

import requests
import shutil

url = 'https://www.dropbox.com/s/fgyso9fq40qp1vl/testfiles.tar.gz?dl=0'
r = requests.get(url, stream=True)
path_to_save = "/tmp/data.dload-1"
with open(path_to_save, 'wb') as f:
    shutil.copyfileobj(r.raw, f)  

загружается на /tmp/data.dload-1.

тот же файл, загруженный с помощью wget wget https://www.dropbox.com/s/fgyso9fq40qp1vl/testfiles.tar.gz?dl=0 -O /tmp/data.dload-2

эти два файла имеют одинаковый тип:

(dl)x:x$ file /tmp/data.dload-1 
/tmp/data.dload-1: gzip compressed data, from Unix
(dl)x:x$ file /tmp/data.dload-2 
/tmp/data.dload-2: gzip compressed data, last modified: Thu Apr 26 23:05:15 2018, from Unix

но если их не пометить, получаются разные результаты:

(dl)x:x$ tar -zxvf /tmp/data.dload-1
tar: This does not look like a tar archive
tar: Skipping to next header
tar: Exiting with failure status due to previous errors
(dl) x:x$ tar -zxvf /tmp/data.dload-2
testfiles/a
testfiles/b
(dl)x:x$ 

кто-нибудь знает, почему это может произойти, и, что более важно, как я могу загрузить этот tar-файл с помощью Python (предпочтительно requests)

Это результат r.headers: (dl) x:x$ python dload-test.py {'Server': 'nginx', 'Date': 'Fri, 27 Apr 2018 17:27:06 GMT', 'Content-Type': 'text/html; charset=utf-8', 'Transfer-Encoding': 'chunked', 'Connection': 'keep-alive', 'Vary': 'Accept-Encoding', 'Cache-Control': 'no-cache', 'Content-Security-Policy': "script-src 'unsafe-eval' https://www.dropbox.com/static/compiled/js/ https://www.dropbox.com/static/javascript/ https://www.dropbox.com/static/api/ https://cfl.dropboxstatic.com/static/compiled/js/ https://www.dropboxstatic.com/static/compiled/js/ https://cfl.dropboxstatic.com/static/js/ https://www.dropboxstatic.com/static/js/ https://cfl.dropboxstatic.com/static/previews/ https://www.dropboxstatic.com/static/previews/ https://cfl.dropboxstatic.com/static/api/ https://www.dropboxstatic.com/static/api/ https://cfl.dropboxstatic.com/static/cms/ https://www.dropboxstatic.com/static/cms/ https://www.google.com/recaptcha/ https://www.gstatic.com/recaptcha/ 'unsafe-inline' ; img-src https://* data: blob: ; frame-ancestors 'self' ; default-src 'none' ; frame-src https://* carousel://* dbapi-6://* dbapi-7://* dbapi-8://* itms-apps://* itms-appss://* ; worker-src https://www.dropbox.com/static/serviceworker/ blob: ; style-src https://* 'unsafe-inline' 'unsafe-eval' ; connect-src https://* ws://127.0.0.1:*/ws ; object-src 'self' https://cfl.dropboxstatic.com/static/ https://www.dropboxstatic.com/static/ https://flash.dropboxstatic.com https://swf.dropboxstatic.com https://dbxlocal.dropboxstatic.com ; media-src https://* blob: ; font-src https://* data: ; child-src https://www.dropbox.com/static/serviceworker/ blob: ; form-action 'self' https://www.dropbox.com/ https://dl-web.dropbox.com/ https://photos.dropbox.com/ https://accounts.google.com/ https://api.login.yahoo.com/ https://login.yahoo.com/ ; base-uri 'self' api-stream.dropbox.com showbox-tr.dropbox.com ; report-uri https://www.dropbox.com/csp_log", 'Dropbox-Streaming': 'V=1', 'Pragma': 'no-cache', 'Referrer-Policy': 'origin-when-cross-origin', 'Set-Cookie': 'locale=en; Domain=dropbox.com; expires=Wed, 26 Apr 2023 17:27:06 GMT; Path=/; secure, gvc=OTU0NjExNzUwNjc0NjQxNzgwMzE0OTgzMzkzNjc3MzM5OTYzNzc%3D; expires=Wed, 26 Apr 2023 17:27:06 GMT; httponly; Path=/; secure, flash=; Domain=dropbox.com; expires=Fri, 27 Apr 2018 17:27:06 GMT; Path=/; secure, puc=; expires=Fri, 27 Apr 2018 17:27:06 GMT; httponly; Path=/; secure, bang=; Domain=dropbox.com; expires=Fri, 27 Apr 2018 17:27:06 GMT; Path=/; secure, seen-sl-signup-modal=VHJ1ZQ%3D%3D; expires=Sun, 27 May 2018 17:27:06 GMT; httponly; Path=/; secure, t=HlsAKcFI_HJWteio0_5ELyFf; Domain=dropbox.com; expires=Mon, 26 Apr 2021 17:27:06 GMT; httponly; Path=/; secure, __Host-js_csrf=HlsAKcFI_HJWteio0_5ELyFf; expires=Mon, 26 Apr 2021 17:27:06 GMT; Path=/; secure', 'X-Content-Type-Options': 'nosniff', 'X-Dropbox-Request-Id': 'b028e94ce7b814c7f25fb753449b641a', 'X-Frame-Options': 'DENY', 'X-Robots-Tag': 'noindex, nofollow, noimageindex', 'X-Xss-Protection': '1; mode=block', 'Strict-Transport-Security': 'max-age=15552000; includeSubDomains', 'Content-Encoding': 'gzip'}

Ответы [ 2 ]

0 голосов
/ 27 апреля 2018

Это безумие, но изменение 0 в конце URL на 1 работает. мотивировано этим ТАК .

0 голосов
/ 27 апреля 2018

Проблема в том, что файл сжимается в gzip, даже если это уже сжатый файл (как видно из поля 'Content-Encoding': 'gzip' в r.headers).

Вы используете заголовки запросов по умолчанию как для requests, так и для wget. По умолчанию они оба отправят что-то вроде 'Accept-Encoding: gzip, deflate'. (Вы можете увидеть это, если распечатаете r.request.headers.) Таким образом, сервер может легко сжать файл и отправить его обратно с заголовком 'Content-Encoding: gzip'.

И wget, и requests по умолчанию обнаружат этот заголовок и прозрачно декодируют данные для вас - но вы явно указали requests не , чтобы сделать это, и прочитали необработанные данные как есть.

Таким образом, вы в конечном итоге сохраняете файл, который представляет собой сжатый архив gzip-gzip-tarball. Очевидно, что file сообщит, что как gzip compressed data, а tar -z сообщит, что находится внутри gzip does not look like a tar archive, потому что это не так, это архив gzip tar.

Наименьшее исправление - вручную добавить headers={'Accept-Encoding': 'identity'} к вашему запросу.


Вы можете задаться вопросом, почему сервер пытается сжать gzip-файл - только потому, что вы сказали, что может принять gzip , не означает, что вы требуете gzip, право?

Если вы посмотрите на RFC 2616 и RFC 7231 , сервер должен выбрать кодировку с наибольшим qvalue (весом), указанным клиентом, который он может поддерживать ( разрыв связи по некоторой эвристике, которая не указана). Если ваш пользовательский агент явно запрашивает 'gzip, deflate', предоставление вам identity будет неправильным, если на самом деле невозможно сделать иначе, не слегка глупо.

...