Повреждение вызвано следующим кодом на сервере:
// Loop to receive all the data sent by the client.
while ((stream.Read(bytes, 0, bytes.Length)) != 0)
{
data.AddRange(bytes);
}
stream.Read
не всегда будет заполнять буфер bytes
. Он не будет заполнен, если в сокете TCP больше нет доступных данных или при чтении последнего фрагмента сообщения (если он не является точным кратным размеру буфера).
Вызов data.AddRange
добавляет все из bytes
(при условии, что он всегда заполнен). В результате это иногда приводит к добавлению данных из предыдущего вызова в stream.Read
. Чтобы исправить это, вам нужно сохранить количество байтов, возвращаемых Read
, и добавить только это количество байтов:
int length;
while ((length = stream.Read(bytes, 0, bytes.Length)) != 0)
{
var copy = new byte[length];
Array.Copy(bytes, 0, copy, 0, length);
data.AddRange(copy);
}
Обратите внимание, что вы можете реструктурировать свой код для повышения производительности и использования памяти (и, возможно, облегчить чтение в результате). Вместо того, чтобы читать все данные в память на клиенте перед отправкой, вы можете просто написать прямо в NetworkStream
. На сервере вам не нужно копировать все данные из потока в память. Вы можете считать 4-байтовую длину имени файла и декодировать его, затем прочитать и декодировать имя файла и, наконец, скопировать оставшуюся часть потока непосредственно в FileStream
(BinaryWriter
не требуется).
Стоит также отметить, что вы создаете выходной файл с FileMode.Append
. Это означает, что каждый отправленный файл будет добавлен к предыдущей копии с тем же именем. Вместо этого вы можете использовать FileMode.Create
, что перезапишет, если файл уже существует.