2016-10-16 2 views
1

У меня есть простой сервер на моем ПК с Windows, написанный на питоне, который читает файлы из каталога, а затем отправляет файл клиенту через TCP.Сервер Python отправляет усеченные изображения по TCP

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

Как ни странно, разные изображения усекаются разной длины, но это согласовано для каждого изображения.
Например, конкретный 1 МБ JPG всегда принимается как 95 байтов. Другое изображение, которое должно быть 7 КБ, принимается как 120 байт.

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

Я пробовал три разных способа чтения сервером файлов, но все они имеют одинаковый результат.

Вот отрывок из чтения и отправки файлов:

print ("Cache size=" + str(os.stat(filename).st_size)) 

#1st attempt, using readlines 
fileobj = open(filename, "r") 
cacheBuffer = fileobj.readlines() 
for i in range(0, len(cacheBuffer)): 
    tcpCliSock.send(cacheBuffer[i]) 

#2nd attempt, using line, same result 
with open(filename) as f: 
    for line in f: 
     tcpCliSock.send(f) 

#3rd attempt, using f.read(), same result 
with open(filename) as f: 
    tcpCliSock.send(f.read()) 

Скрипт выводит на консоль размер файла read и количество байтов matche s оригинальное изображение. Таким образом, это доказывает, что проблема заключается в отправке, не так ли?
Если проблема связана с отправкой, что я могу изменить для правильного отображения всего изображения?

ответ

3

Поскольку вы имеете дело с изображениями, которые являются двоичными файлами, вам необходимо открыть файлы в двоичном режиме.

open(filename, 'rb') 

Из документации Python для open():

по умолчанию использовать текстовый режим, который может конвертировать '\n' символы в представлении конкретной платформы по написанию и обратно на чтение. Таким образом, при открытии двоичного файла вы должны добавить 'b' в значение режима, чтобы открыть файл в двоичном режиме, что улучшит переносимость. (Прилагая 'b' полезно даже на системах, которые не лечат двоичными и текстовые файлы по-разному, где он служит в качестве документации.)

Поскольку ваш сервер работает на Windows, как вы read файл, Python является преобразованием каждого \r\n он видит \n. Для текстовых файлов это приятно: вы можете написать независимый от платформы код, который имеет дело только с \n символами. Для двоичных файлов этот полностью развращает ваши данные.Вот почему при работе с бинарными файлами важно использовать 'b', но также важно оставить его при работе с текстовыми файлами.


Кроме того, как TCP является протоколом потока, то лучше поток данных в гнездо в более мелкие куски. Это позволяет избежать необходимости считывать весь файл в память, что уменьшит использование памяти. Пример:

with open(filename, 'rb') as f: 
    while True: 
     data = f.read(4096) 
     if len(data) == 0: 
      break 
     tcpCliSock.send(data) 
+0

Подтвержденная работа! – Bort

+0

Есть ли причина НЕ ВСЕГДА использовать двоичный режим? Это создаст проблему для любого текста? – Bort

Смежные вопросы