Serving a binary file from a web server to a client

Usually, when I want to transfer the text file of the web server to the client, this is what I did

import cgi print "Content-Type: text/plain" print "Content-Disposition: attachment; filename=TEST.txt" print filename = "C:\\TEST.TXT" f = open(filename, 'r') for line in f: print line 

The ANSI file works very well. However, let's say I have a binary file a.exe (this file is in the secret path of the web server and the user will not have direct access to this directory path). I want to use a similar method for transmission. How can i do this?

  • What content type should I use?
  • Using print seems to have corrupted content received on the client side. What is the correct method?

I am using the following code.

 #!c:/Python27/python.exe -u import cgi print "Content-Type: application/octet-stream" print "Content-Disposition: attachment; filename=jstock.exe" print filename = "C:\\jstock.exe" f = open(filename, 'rb') for line in f: print line 

However, when I compare the downloaded file with the original file, it seems that there are additional spaces (or more) for each individual line.

alt text

+4
source share
4 answers

Agree to the above posters about the 'rb' and Content-Type headers.

Additionally:

 for line in f: print line 

This can be a problem when dealing with \n or \r\n bytes in a binary. Perhaps it would be better to do something like this:

 import sys while True: data = f.read(4096) sys.stdout.write(data) if not data: break 

Assuming this runs on Windows in a CGI environment, you need to start the python process with the -u argument, this ensures that stdout is not in text mode

+3
source

The .exe content type is a typical application/octet-stream .
You might want to read your file using open(filename, 'rb') , where b means binary.

To avoid the problem with spaces, you can try:

 sys.stdout.write(open(filename,"rb").read()) sys.stdout.flush() 

or even better, depending on the size of your file, use the Knio approach:

 fo = open(filename, "rb") while True: buffer = fo.read(4096) if buffer: sys.stdout.write(buffer) else: break fo.close() 
+1
source

When opening a file, you can use open(filename, 'rb') - the 'b' flag designates it as binary. For a regular handler, you can use some form of mime magic (I am not familiar with its use with Python, I only once used it with PHP a couple of years ago). For a specific case .exe application/octet-stream .

+1
source

For those using Windows Server 2008 or 2012 and Python 3, here's the update ...

After many hours of experimentation, I found the following to work reliably:

 import io with io.open(sys.stdout.fileno(),"wb") as fout: with open(filename,"rb") as fin: while True: data = fin.read(4096) fout.write(data) if not data: break 
0
source

Source: https://habr.com/ru/post/1333161/


All Articles