Winzip cannot open an archive created by python shutil.make_archive on windows. On ubuntu archive manager does fine

StackOverflow https://stackoverflow.com//questions/12697431

  •  12-12-2019
  •  | 
  •  

Вопрос

I am trying to return a zip file in django http response, the code goes something like...

archive = shutil.make_archive('testfolder', 'zip', MEDIA_ROOT, 'testfolder')
response = HttpResponse(FileWrapper(open(archive)),
                           content_type=mimetypes.guess_type(archive)[0])
response['Content-Length'] = getsize(archive)
response['Content-Disposition'] = "attachment; filename=test %s.zip" % datetime.now()
return response

Now when this code is executed on ubuntu the resulting downloaded file opens without any issue, but when its executed on windows the file created does not open in winzip (gives error 'Unsupported Zip Format').

Is there something very obvious I am missing here? Isn't python code supposed to be portable?

EDIT:

Thanks to J.F. Sebastian for his comment...

There was no problem in creating the archive, it was reading it back into the request. So, the solution is to change second line of my code from,

response = HttpResponse(FileWrapper(open(archive)),
                           content_type=mimetypes.guess_type(archive)[0])

to,

response = HttpResponse(FileWrapper(open(archive, 'rb')),  # notice extra 'rb'
                           content_type=mimetypes.guess_type(archive)[0])

checkout, my answer to this question for more details...

Это было полезно?

Решение 2

Thanks to J.F. Sebastian for his comment...

I'll still write the solution here in detail...

There was no problem in creating the archive, it was reading it back into the request. So, the solution is to change second line of my code from,

response = HttpResponse(FileWrapper(open(archive)),
                           content_type=mimetypes.guess_type(archive)[0])

to,

response = HttpResponse(FileWrapper(open(archive, 'rb')),  # notice extra 'rb'
                           content_type=mimetypes.guess_type(archive)[0])

because apparently, hidden somewhere in python 2.3 documentation on open:

The most commonly-used values of mode are 'r' for reading, 'w' for writing (truncating the file if it already exists), and 'a' for appending (which on some Unix systems means that all writes append to the end of the file regardless of the current seek position). If mode is omitted, it defaults to 'r'. The default is to use text mode, which may convert '\n' characters to a platform-specific representation on writing and back on reading. Thus, when opening a binary file, you should append 'b' to the mode value to open the file in binary mode, which will improve portability. (Appending 'b' is useful even on systems that don’t treat binary and text files differently, where it serves as documentation.) See below for more possible values of mode.

So, in simple terms while reading binary files, using open(file, 'rb') increases portability of your code (it certainly did in this case)

Now, it extracts without troubles, on windows...

Другие советы

The code you have written should work correctly. I've just run the following line from your snippet to generate a zip file and was able to extract on Linux and Windows.

archive = shutil.make_archive('testfolder', 'zip', MEDIA_ROOT, 'testfolder')

There is something funny and specific going on. I recommend you check the following:

  1. Generate the zip file outside of Django with a script that just has that one liner. Then try and extract it on a Windows machine. This will help you rule out anything going on relating to Django, web server or browser
  2. If that works then look at exactly what is in the folder you compressed. Do the files have any funny characters in their names, are there strange file types, or super long filenames.
  3. Run a md5 checksum on the zip file in Windows and Linux just to make absolutely sure that the two files are byte by byte identical. To rule out any file corruption that might have occured.
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top