web-dev-qa-db-fra.com

python demande le téléchargement de fichier

J'effectue une tâche simple consistant à télécharger un fichier à l'aide de la bibliothèque de requêtes Python. J'ai cherché Stack Overflow et personne ne semblait avoir le même problème, à savoir que le fichier n'était pas reçu par le serveur:

import requests
url='http://nesssi.cacr.caltech.edu/cgi-bin/getmulticonedb_release2.cgi/post'
files={'files': open('file.txt','rb')}
values={'upload_file' : 'file.txt' , 'DB':'photcat' , 'OUT':'csv' , 'SHORT':'short'}
r=requests.post(url,files=files,data=values)

Je remplis la valeur du mot clé 'upload_file' avec mon nom de fichier, car si je le laisse vide, il est indiqué

Error - You must select a file to upload!

Et maintenant je reçois

File  file.txt  of size    bytes is  uploaded successfully!
Query service results:  There were 0 lines.

Ce qui n'apparaît que si le fichier est vide. Je suis donc coincé sur la façon d'envoyer mon fichier avec succès. Je sais que le fichier fonctionne parce que si je vais sur ce site et remplis manuellement le formulaire, il retourne une belle liste d'objets correspondants, ce que je recherche après. J'apprécierais vraiment tous les conseils.

Quelques autres sujets liés (mais ne répondant pas à mon problème):

81
scichris

Si upload_file est censé être le fichier, utilisez:

files = {'upload_file': open('file.txt','rb')}
values = {'DB': 'photcat', 'OUT': 'csv', 'SHORT': 'short'}

r = requests.post(url, files=files, data=values)

et requests enverra un corps en plusieurs parties POST avec le champ upload_file défini sur le contenu du fichier file.txt.

Le nom de fichier sera inclus dans l'en-tête mime pour le champ spécifique:

>>> import requests
>>> open('file.txt', 'wb')  # create an empty demo file
<_io.BufferedWriter name='file.txt'>
>>> files = {'upload_file': open('file.txt', 'rb')}
>>> print(requests.Request('POST', 'http://example.com', files=files).prepare().body.decode('ascii'))
--c226ce13d09842658ffbd31e0563c6bd
Content-Disposition: form-data; name="upload_file"; filename="file.txt"


--c226ce13d09842658ffbd31e0563c6bd--

Notez le paramètre filename="file.txt".

Vous pouvez utiliser un tuple pour la valeur de mappage files, avec entre 2 et 4 éléments, si vous avez besoin de plus de contrôle. Le premier élément est le nom du fichier, suivi du contenu, d'une valeur facultative d'en-tête content-type et d'un mappage facultatif d'en-têtes supplémentaires:

files = {'upload_file': ('foobar.txt', open('file.txt','rb'), 'text/x-spam')}

Ceci définit un autre nom de fichier et type de contenu, en laissant de côté les en-têtes facultatifs.

Si vous souhaitez que l'ensemble du corps POST soit extrait d'un fichier (aucun autre champ ne soit spécifié), n'utilisez pas le paramètre files, postez-le directement sous le nom data. Vous voudrez peut-être aussi définir un en-tête Content-Type, car aucun ne sera défini autrement.

160
Martijn Pieters

(2018) La nouvelle bibliothèque de requêtes python a simplifié ce processus. Nous pouvons utiliser la variable 'fichiers' pour indiquer que nous souhaitons télécharger un fichier codé en plusieurs parties.

url = 'http://httpbin.org/post'
files = {'file': open('report.xls', 'rb')}

r = requests.post(url, files=files)
r.text
19
laycat

Client Uplaod

Si vous souhaitez télécharger un seul fichier avec la bibliothèque Python requests, demandez alors lib prend en charge les transferts en contin , ce qui vous permet de envoyer des fichiers volumineux ou des flux sans les lire en mémoire .

with open('massive-body', 'rb') as f:
    requests.post('http://some.url/streamed', data=f)

Du côté serveur

Stockez ensuite le fichier sur le côté server.py de manière à enregistrer le flux dans le fichier sans le charger dans la mémoire. Voici un exemple d'utilisation de pload de fichiers Flask .

@app.route("/upload", methods=['POST'])
def upload_file():
    from werkzeug.datastructures import FileStorage
    FileStorage(request.stream).save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
    return 'OK', 200

Ou utilisez werkzeug Form Data Parsing comme indiqué dans un correctif pour le problème de " les fichiers volumineux surchargeant de mémoire) " afin d'éviter utilisation inefficace de la mémoire lors du téléchargement de fichiers volumineux (fichier st 22 GiB en ~ 60 secondes. L’utilisation de la mémoire est constante à environ 13 Mio.).

@app.route("/upload", methods=['POST'])
def upload_file():
    def custom_stream_factory(total_content_length, filename, content_type, content_length=None):
        import tempfile
        tmpfile = tempfile.NamedTemporaryFile('wb+', prefix='flaskapp', suffix='.nc')
        app.logger.info("start receiving file ... filename => " + str(tmpfile.name))
        return tmpfile

    import werkzeug, flask
    stream, form, files = werkzeug.formparser.parse_form_data(flask.request.environ, stream_factory=custom_stream_factory)
    for fil in files.values():
        app.logger.info(" ".join(["saved form name", fil.name, "submitted as", fil.filename, "to temporary file", fil.stream.name]))
        # Do whatever with stored file at `fil.stream.name`
    return 'OK', 200
11
gihanchanuka