Обслуживание двоичного файла с веб-сервера на клиент - PullRequest
5 голосов
/ 23 декабря 2010

Обычно, когда я хочу передать текстовый файл веб-сервера клиенту, вот что я сделал

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

Очень хорошо работает для файла ANSI. Однако, скажем, у меня есть двоичный файл a.exe (этот файл находится в секретном пути веб-сервера, и у пользователя не должно быть прямого доступа к этому пути каталога). Я хочу использовать подобный метод для передачи. Как я могу это сделать?

  • Какой тип контента мне следует использовать?
  • При использовании печати поврежденный контент получен на стороне клиента. Какой правильный метод?

Я использую следующий код.

#!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

Однако, когда я сравниваю загруженный файл с оригинальным файлом, кажется, что после каждой отдельной строки появляется дополнительный пробел (или больше).

alt text

Ответы [ 4 ]

3 голосов
/ 23 декабря 2010

Согласны с вышеприведенными плакатами о заголовках 'rb' и Content-Type.

Дополнительно:

for line in f:
    print line

Это может быть проблемой при обнаружении байтов \n или \r\n в двоичном файле. Может быть, лучше сделать что-то вроде этого:

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

Предполагая, что это выполняется в Windows в среде CGI, вы захотите запустить процесс python с аргументом -u, это обеспечит отсутствие стандартного вывода в текстовом режиме

1 голос
/ 23 декабря 2010

При открытии файла вы можете использовать open(filename, 'rb') - флаг 'b' помечает его как двоичный файл. Для обычного обработчика вы можете использовать некоторую форму магии пантомимы (я не знаком с ее использованием из Python, я использовал ее только из PHP пару лет назад). Для конкретного случая .exe равно application/octet-stream.

1 голос
/ 23 декабря 2010

Тип содержимого .exe обычно application/octet-stream.
Возможно, вы захотите прочитать ваш файл, используя open(filename, 'rb'), где b означает двоичный файл.

Чтобы избежать проблемы с пробелами, вы можете попробовать:

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

или даже лучше, в зависимости от размера вашего файла, используйте подход Knio :

fo = open(filename, "rb")
while True:
    buffer = fo.read(4096)
    if buffer:
        sys.stdout.write(buffer)
    else:
        break
fo.close()
0 голосов
/ 19 июля 2015

Для тех, кто использует Windows Server 2008 или 2012 и Python 3, вот обновление ...

После многих часов экспериментов я обнаружил, что следующее работает надежно:

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
...