Seite 1 von 1
Probleme mit zipfile unter windows 2000...
Verfasst: Sonntag 26. Februar 2006, 22:37
von jens
Irgendwie produiziert zipfile keine gültige ZIPs unter Windows 2000. Ich weiß nur nicht warum.
Erstmal ein Auszug aus dem Code:
Code: Alles auswählen
buffer = StringIO.StringIO()
z = zipfile.ZipFile(buffer, "w")
for file_info in files:
filename = file_info[0]
abs_path = posixpath.join(self.request_path, filename)
arcname = posixpath.join(artist, album, filename)
z.write(abs_path, arcname)
z.close()
buffer.seek(0,2) # Am Ende der Daten springen
buffer_len = buffer.tell() # Aktuelle Position
buffer.seek(0) # An den Anfang springen
filename = posixpath.split(self.request_path)[-1]
self.request.headers['Content-Disposition'] = 'attachment; filename="%s.zip"' % filename
self.request.headers['Content-Length'] = '%s' % buffer_len
self.request.headers['Content-Transfer-Encoding'] = 'binary'
self.request.headers['Content-Type'] = 'application/octet-stream;'# charset=utf-8'
def send_data(buffer):
while 1:
data = buffer.read(2048)
if not data:
return
yield data
time.sleep(0.1)
self.request.send_response(send_data(buffer))
Unter Linux (Ubuntu) klappt alles richtig. Unter Windows 2000 sind die ZIP-Dateien unbrauchbar

Anscheinend wäre der Header defekt. Mit einem Hex-Editor sieht alles "normal" aus...
Jemand einen Tipp für mich?
Verfasst: Sonntag 26. Februar 2006, 22:48
von jens
Hab das ganze mal umgebaut, das man es lokal testen kann. Es werden dabei einfach alle Dateien im aktuellen Verzeichnis in test.zip eingepackt. Bei mir unter XP geht das einwandfrei:
Code: Alles auswählen
import os, posixpath, StringIO, zipfile, time
def create():
buffer = StringIO.StringIO()
z = zipfile.ZipFile(buffer, "w")
artist = "test_verz_1"
album = "test_verz_2"
for item in os.listdir("."):
if os.path.isfile(item):
arcname = posixpath.join(artist, album, item)
z.write(item, arcname)
z.close()
buffer.seek(0,2) # Am Ende der Daten springen
buffer_len = buffer.tell() # Aktuelle Position
buffer.seek(0) # An den Anfang springen
def send_data(buffer):
while 1:
data = buffer.read(2048)
if not data:
return
yield data
time.sleep(0.000001)
f = file("test.zip", "wb")
for block in send_data(buffer):
f.write(block)
f.close()
create()
Verfasst: Montag 27. Februar 2006, 08:21
von modelnine
Mach aus der Content-Type Zeile mal folgendes:
Code: Alles auswählen
self.request.headers['Content-Transfer-Encoding'] = '8bit'
self.request.headers['Content-Type'] = 'application/octet-stream'# ;charset=utf-8'
Bei Content-Transfer-Encoding ist 8bit eigentlich identisch zu binary (wobei ersteres gängiger ist, zumindest im Zusammenhang mit MIME), aber es so zu probieren kann ja mal nicht schaden.

Re: Probleme mit zipfile unter windows 2000...
Verfasst: Montag 27. Februar 2006, 09:57
von gerold
jens hat geschrieben:Unter Linux (Ubuntu) klappt alles richtig. Unter Windows 2000 sind die ZIP-Dateien unbrauchbar

Anscheinend wäre der Header defekt. Mit einem Hex-Editor sieht alles "normal" aus...
Hi Jens!
Das gleiche Problem hatte ich auch. Allerdings ging es mir dann so auf die Nerven, dass ich auf das Modul "tarfile" ausgewichen bin.
Ich glaube, dass der Unterschied ein Zeilenumbruch am Ende des Files war.
lg
Gerold

Verfasst: Montag 27. Februar 2006, 12:22
von jens
Guter Tipp. Neben tar könnte ich es auch mit bz2 probieren.
Hab keinen Bug bei
http://sourceforge.net/tracker/?group_i ... tid=105470 gefunden. Ob es nun wirklich an der zlibn liegt?
Verfasst: Mittwoch 1. März 2006, 10:10
von jens
Ich hab das Problem in die deutsche Maillingliste
http://python.net/pipermail/python-de/2 ... 07591.html geschildert. Allerdings bisher ohne Resonanz.
Leider kann ich selber nicht testen, da ich kein Win2000 hab.
@gerold: Kannst du mehr zum Problem sagen?
Verfasst: Mittwoch 1. März 2006, 10:35
von gerold
jens hat geschrieben:@gerold: Kannst du mehr zum Problem sagen?
Hi Jens!
Tut mir leid, ist schon zu lange her.
lg
Gerold

Verfasst: Donnerstag 2. März 2006, 19:28
von jens
So, ich hab jetzt alles auf tarfile umgestellt und auch kein StringIO benutzt, dennoch sind die Archive defekt
EDIT: Mit 'Content-Transfer-Encoding' = '8bit' geht es auch nicht...
Verfasst: Donnerstag 2. März 2006, 19:37
von Python 47
Hast du mal Modelnine´s Tipp ausprobiert?
Verfasst: Donnerstag 2. März 2006, 19:49
von gerold
jens hat geschrieben:Bei mir unter XP geht das einwandfrei:
Code: Alles auswählen
import os, posixpath, StringIO, zipfile, time
def create():
buffer = StringIO.StringIO()
z = zipfile.ZipFile(buffer, "w")
...
Hi Jens!
Ich habe diesen Code bei mir ausprobiert. Er funktioniert einwandfrei. Und das, obwohl du die Funktion "buffer()" überschrieben hast.
Windows 2000 -- Alle Servicepacks und Updates die es gibt.
Python 2.4.1
lg
Gerold

Verfasst: Donnerstag 2. März 2006, 20:09
von jens
Also ich hab nun mal auf beiden Systemen ein TarFile erzeugt und mit einem Hex-Editor verglichen... Beim 2000er sind im Datenstrom ein zusätzliche Zeichen drin:
...a8ed 9d0a 75c0 0036... <- funktioniertendes tar
...a8ed 9d0d 0a75 c000... <- defektes Win2000 tar
Verfasst: Donnerstag 2. März 2006, 20:15
von jens
Hier wieder eine herraus gelöste Version:
Code: Alles auswählen
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import os, posixpath, time
from tempfile import NamedTemporaryFile
from tarfile import TarFile
def create():
temp = NamedTemporaryFile(prefix="PyDown_")
tar = TarFile(mode="w", fileobj=temp)
artist = "test_verz_1"
album = "test_verz_2"
for item in os.listdir("."):
if os.path.isfile(item):
arcname = posixpath.join(artist, album, item)
tar.add(item, arcname)
tar.close()
temp.seek(0,2) # Am Ende der Daten springen
temp_len = temp.tell() # Aktuelle Position
temp.seek(0) # An den Anfang springen
def send_data(temp):
while 1:
data = temp.read(2048)
if not data:
return
yield data
time.sleep(0.000001)
f = file("test.tar", "wb")
for block in send_data(temp):
f.write(block)
f.close()
create()
Verfasst: Donnerstag 2. März 2006, 20:21
von mitsuhiko
jens hat geschrieben:...a8ed 9d0a 75c0 0036... <- funktioniertendes tar
...a8ed 9d0d 0a75 c000... <- defektes Win2000 tar
\x0d == \r
\x0a == \n
Damit wäre klar, dass da windows seine carrige returns reinhaut.
Verfasst: Donnerstag 2. März 2006, 21:43
von jens
Also bin ein wenig weiter... Es liegt nicht an colubrid und nicht am zip/tar-File selber... Auch ist kein 2000 sondern doch ein XP im Spiel... Anscheinend liegt es irgendwie am Windows XAMPP...
Ich hab ein neues kleineres Testskript geschrieben:
Code: Alles auswählen
#!D:\python\python24\python.exe
# -*- coding: UTF-8 -*-
#~ print "Content-type: text/html; charset=utf-8\n"
#~ import cgitb;cgitb.enable()
import sys, os, posixpath, time, glob
from tempfile import NamedTemporaryFile
from tarfile import TarFile
temp = NamedTemporaryFile(prefix="PyDown_")
tar = TarFile(mode="w", fileobj=temp)
for item in glob.glob("*.mp3"):
tar.add(item)
tar.close()
print "Content-Disposition: attachment; filename=test.tar"
#~ print 'Content-Transfer-Encoding: binary'
print "Content-Transfer-Encoding: 8bit"
print "Content-Type: application/octet-stream;\n"# charset=utf-8\n'
f = file("test.tar", "wb")
while 1:
data = temp.read(2048)
if not data:
break
f.write(data)
sys.stdout.write(data)
f.close()
temp.close()
Die parallel erzeugte Datei ist in Ordnung... Die downgeloadete Datei ist defekt

Verfasst: Donnerstag 2. März 2006, 22:20
von gerold
Hi Jens!
Dieser Code erzeugt identische Files beim Aufruf mit
Code: Alles auswählen
#!D:\python\python24\python.exe
# -*- coding: UTF-8 -*-
#~ print "Content-type: text/html; charset=utf-8\n"
#~ import cgitb;cgitb.enable()
import sys, os, posixpath, time, glob
from tempfile import NamedTemporaryFile
from tarfile import TarFile
temp = NamedTemporaryFile(prefix="PyDown_")
tar = TarFile(mode="w", fileobj=temp)
for item in glob.glob("*.txt"):
tar.add(item)
tar.close()
#print "Content-Disposition: attachment; filename=test.tar"
#~ print 'Content-Transfer-Encoding: binary'
#print "Content-Transfer-Encoding: 8bit"
#print "Content-Type: application/octet-stream;\n"# charset=utf-8\n'
# force input/output to binary
if sys.platform == "win32":
import msvcrt
msvcrt.setmode(sys.stdin.fileno(), os.O_BINARY)
msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
f = file("test.tar", "wb")
temp.seek(0)
while 1:
data = temp.read(2048)
if not data:
break
f.write(data)
sys.stdout.write(data)
f.close()
temp.close()
lg
Gerold

Verfasst: Samstag 4. März 2006, 19:12
von gerold
gerold hat geschrieben:Dieser Code erzeugt identische Files beim Aufruf mit
Hi Jens!
Wenn man die Kommentarzeichen vor den "print"-Anweisungen, die für das CGI notwendig sind, wieder entfernt, dann funktioniert es
auch mit XAMPP unter Windows 2000.
Code: Alles auswählen
print "Content-Disposition: attachment; filename=test.tar"
print "Content-Transfer-Encoding: 8bit"
print "Content-Type: application/octet-stream;\n"
# force input/output to binary
if sys.platform == "win32":
import msvcrt
msvcrt.setmode(sys.stdin.fileno(), os.O_BINARY)
msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
[...]
temp.seek(0)
Ich habe dieses Skript soeben getestet.
Hier das gesamte Skript, genau so wie ich es getestet habe. Danach habe ich die Ergebnisse mit "cmp" vom Cygwin verglichen und zum Test mit WinZip geöffnet. Allerdings habe ich nur Textdateien komprimiert. Vielleicht versuche ich es später noch mit anderen Dateien, aber erst mal mache ich Schluß.
Code: Alles auswählen
#!C:\Python24\python.exe
# -*- coding: iso-8859-1 -*-
#~ print "Content-type: text/html; charset=utf-8\n"
#~ import cgitb;cgitb.enable()
import sys, os, posixpath, time, glob
from tempfile import NamedTemporaryFile
from tarfile import TarFile
temp = NamedTemporaryFile(prefix="PyDown_")
tar = TarFile(mode="w", fileobj=temp)
for item in glob.glob("*.txt"):
tar.add(item)
tar.close()
print "Content-Disposition: attachment; filename=test.tar"
#~ print 'Content-Transfer-Encoding: binary'
print "Content-Transfer-Encoding: 8bit"
print "Content-Type: application/octet-stream;\n"# charset=utf-8\n'
# force input/output to binary
if sys.platform == "win32":
import msvcrt
msvcrt.setmode(sys.stdin.fileno(), os.O_BINARY)
msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
f = file("test.tar", "wb")
temp.seek(0)
while 1:
data = temp.read(2048)
if not data:
break
f.write(data)
sys.stdout.write(data)
f.close()
temp.close()
lg
Gerold

Verfasst: Montag 6. März 2006, 14:24
von jens
Ich dummie

Ich hatte wahrscheinlich das .seek(0) vergessen, deswegen klappte es nicht mit dem Test-Skript
Auf jeden Fall scheint es nun zu klappen!!! Dank dir, für deine Geduld.
Ich Frage mich, warum man überhaupt explizit den stdout auf binär setzten muß?
Verfasst: Montag 6. März 2006, 22:13
von BlackJack
jens hat geschrieben:Ich Frage mich, warum man überhaupt explizit den stdout auf binär setzten muß?
Weil Windows sonst aus jedem '\n' ein '\r\n' macht.
Verfasst: Montag 6. März 2006, 22:14
von jens
Wie nett doch Windows ist
