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:

  • Wie kann ich binäre Hex-formatierte Daten in Python entpacken?
  • Float auf binär
  • Wie man xor mit python
  • Binärpuffer in Python
  • Einen mit Python-Pickle gespeicherten Eintrag entfernen oder bearbeiten
  • Binäre Darstellung des Schwimmers in Python (Bits nicht hex)
  •  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.

  • Dateien können nicht mit Pickle- und Multiplet-Modulen geladen werden
  • Wie erfasse ich die Passwort-Eingabeaufforderung
  • Django - Wie kann ich django.contrib.auth.views.login nach dem Login umleiten?
  • Wie programmgesteuert man sich in der Webseite in Python anmeldet
  • Homepage login form Django
  • Python - Abrufen von Informationen aus einer Syslog-Datei
  • 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.