web-dev-qa-db-fra.com

Comment envoyer des fichiers Zip dans le cadre python Flask?

J'ai un serveur flask qui saisit les données binaires de plusieurs fichiers différents d'une base de données et les place dans un objet python 'zipfile'. Je veux envoyer le fichier Zip généré avec mon code en utilisant la méthode "send_file" du flacon.

À l'origine, j'ai pu envoyer des fichiers non Zip avec succès en utilisant le BytesIO (bin) comme premier argument de send_file, mais pour une raison quelconque, je ne peux pas faire la même chose avec mon fichier Zip généré. Il donne l'erreur:

'ZipFile' n'a pas d'interface tampon.

Comment envoyer cet objet de fichier Zip à l'utilisateur avec Flask?

Voici mon code:

@app.route("/getcaps",methods=['GET','POST'])
def downloadFiles():
    if request.method == 'POST':
        mongo = MongoDAO('localhost',27017)
        identifier = request.form['CapsuleName']
        password = request.form['CapsulePassword']
        result = mongo.getCapsuleByIdentifier(identifier,password)
        zf = zipfile.ZipFile('capsule.Zip','w')
        files = result['files']
        for individualFile in files:
            data = zipfile.ZipInfo(individualFile['fileName'])
            data.date_time = time.localtime(time.time())[:6]
            data.compress_type = zipfile.Zip_DEFLATED
            zf.writestr(data,individualFile['fileData'])
        return send_file(BytesIO(zf), attachment_filename='capsule.Zip', as_attachment=True)
    return render_template('download.html')
23
idungotnosn

BytesIO() doit être passé bytes data, mais un objet ZipFile() n'est pas bytes-data; vous avez en fait créé un fichier sur votre disque dur.

Vous pouvez créer une ZipFile() en mémoire en utilisant BytesIO()comme base:

memory_file = BytesIO()
with zipfile.ZipFile(memory_file, 'w') as zf:
    files = result['files']
    for individualFile in files:
        data = zipfile.ZipInfo(individualFile['fileName'])
        data.date_time = time.localtime(time.time())[:6]
        data.compress_type = zipfile.Zip_DEFLATED
        zf.writestr(data, individualFile['fileData'])
memory_file.seek(0)
return send_file(memory_file, attachment_filename='capsule.Zip', as_attachment=True)

L'instruction with garantit que l'objet ZipFile() est correctement fermé lorsque vous avez terminé d'ajouter des entrées, ce qui provoque l'écriture de la bande-annonce requise dans l'objet fichier en mémoire. L'appel memory_file.seek(0) est nécessaire pour "rembobiner" la position de lecture-écriture de l'objet fichier au début.

39
Martijn Pieters