Wie kann man Zip-Dateien (oder andere Binärdateien) durch cgi in Python bereitstellen?

Ich kodiere eine kleine Website mit Python und CGI, wo Benutzer zip-Dateien hochladen und Dateien herunterladen können, die von anderen Benutzern hochgeladen werden. Derzeit bin ich in der Lage, korrekt das Reißverschluss hochzuladen, aber ich habe einige Schwierigkeiten, Dateien ordnungsgemäß an den Benutzer zu senden. Mein erster Ansatz war:

file = open('../../data/code/' + filename + '.zip','rb') print("Content-type: application/octet-stream") print("Content-Disposition: filename=%s.zip" %(filename)) print(file.read()) file.close() 

Aber bald merkte ich, dass ich die Datei als Binär senden musste, also habe ich versucht:

  • Konvertieren Sie Hex zu schwimmen
  • Python-Äquivalent von PHP-Pack
  • Binärdatei in SQLite-Datenbank mit Python einfügen
  • Wie man xor mit python
  • Python-Konvertierung von binärer String zu hexadezimal
  • Python re-Modul, um die binären Daten in einer Textdatei zu ersetzen?
  •  print("Content-type: application/octet-stream") print("Content-Disposition: filename=%s.zip" %(filename)) print('Content-transfer-encoding: base64\r') print( base64.b64encode(file.read()).decode(encoding='UTF-8') ) 

    Und verschiedene Varianten davon. Es funktioniert einfach nicht; Apache hebt "fehlerhaftes Header aus Skript" Fehler, also denke ich, dass ich die Datei auf eine andere Weise kodieren sollte.

  • Python Login Skript; Mehrere Passwörter pro Konto
  • Dateien können nicht mit Pickle- und Multiplet-Modulen geladen werden
  • Flaschenansicht hebt TypeError: 'bool' Objekt ist nicht abrufbar
  • Django-allauth-konfiguration zweifelhaft
  • Verwenden Sie Mechanisieren, um sich bei Megaupload anzumelden
  • Mit einfachem, um sich bei GAE einzuloggen
  • 3 Solutions collect form web for “Wie kann man Zip-Dateien (oder andere Binärdateien) durch cgi in Python bereitstellen?”

    Sie müssen eine leere Zeile nach den Headern ausdrucken und der Content-Disposition-Header fehlt der Typ ( attachment ):

     print("Content-type: application/octet-stream") print("Content-Disposition: attachment; filename=%s.zip" %(filename)) print() 

    Sie können auch eine effizientere Methode zum Hochladen der resultierenden Datei verwenden. Verwenden Sie shutil.copyfileobj() um die Daten in sys.stdout.buffer zu sys.stdout.buffer :

     from shutil import copyfileobj import sys print("Content-type: application/octet-stream") print("Content-Disposition: attachment; filename=%s.zip" %(filename)) print() with open('../../data/code/' + filename + '.zip','rb') as zipfile: copyfileobj(zipfile, sys.stdout.buffer) 

    Sie sollten auf keinen Fall print() für Binärdaten verwenden; Alles was du bekommst ist b'...' Byte Literal Syntax. Das sys.stdout.buffer Objekt ist der zugrundeliegende binäre E / A-Puffer, der Binärdaten direkt auf diese kopiert.

    Der Header ist fehlerhaft, weil aus irgendeinem Grund Python es nach dem Senden der Datei sendet.

    Was Sie tun müssen, ist bündig stdout direkt nach dem Header:

     sys.stdout.flush() 

    Dann legen Sie die Datei kopieren

    Das ist was für mich gearbeitet, ich laufe Apache2 und lade dieses script über cgi. Python 3 ist meine Sprache.

    Möglicherweise müssen Sie die erste Zeile mit Ihrem python 3 bin Pfad ersetzen.

     #!/usr/bin/python3 import cgitb import cgi from zipfile import ZipFile import sys # Files to include in archive source_file = ["/tmp/file1.txt", "/tmp/file2.txt"] # Name and Path to our zip file. zip_name = "zipfiles.zip" zip_path = "/tmp/{}".format(zip_name) with ZipFile( zip_path,'w' ) as zipFile: for f in source_file: zipFile.write(f); # Closing File. zipFile.close() # Setting Proper Header. print ( 'Content-Type:application/octet-stream; name="{}"'.format(zip_name) ); print ( 'Content-Disposition:attachment; filename="{}"\r\n'.format(zip_name) ); # Flushing Out stdout. sys.stdout.flush() bstdout = open(sys.stdout.fileno(), 'wb', closefd=False) file = open(zip_path,'rb') bstdout.write(file.read()) bstdout.flush() 
    Python ist die beste Programmiersprache der Welt.