Я написал код клиента/сервера, который перемещает файлы взад и вперед между системами через Delphi, написанный WebService. Из-за ограничений шлюзов перед службой мне пришлось разделить большие файлы на несколько сообщений. Приведенный ниже код часто работает в моем тестировании. Иногда, однако, на последнем фрагменте данных, похоже, он не попадает в результирующий файл. У меня есть еще одна версия кода, где я добавил подробный журнал на каждом шагу, чтобы проверить текущую позицию в FileStream до и после вызовов writeBuffer и получить размер промежуточного файла. Кажется, что эта версия кода работает каждый раз, и это заставляет меня думать, что я могу столкнуться с какой-то проблемой времени. Должен ли я делать Flush на Stream после каждой записи или чего-то подобного?Созданный файл TFileStream отсутствовал.
responseObj := DocSvc.getDocument(GetFileInHeader, GetFileIn);
while processingGetFile do
begin
chunkID := StrToInt(responseObj.ValidationResults[0].ValidationResultId);
if chunkID = -3 then
begin
processingGetFile := false;
break;
end;
if chunkID = -2 then
begin
if responseObj.opsResponseobj.status then
begin
if responseObj.opsResponseObj.document <> 'NONEWFILE' then
begin
if FileExists2(DesintationFilePath) then
DeleteFile(DesintationFilePath);
Zipfile := TFileStream.Create(DesintationFilePath,FmOpenReadWrite or FmShareDenyNone or fmCreate);
DecodedZipfile := DecodeString(responseObj.opsResponseobj.document);
Zipfile.WriteBuffer(Pointer(DecodedZipfile)^, length(DecodedZipfile));
iniTransmit.WriteString(‘DocumentSection’,string(FileID), responseObj.ValidationResults[0].ReasonCode);
FreeAndNil(Zipfile);
end;
result := true;
processingGetFile := false;
end
else
begin
//Log failure
end;
end
else if chunkID = -1 then
begin
Zipfile.Position := getFileSize(DesintationFilePath);
DecodedZipfile := DecodeString(responseObj.opsResponseObj.document);
Zipfile.WriteBuffer(Pointer(DecodedZipfile)^, Length(DecodedZipfile));
iniTransmit.WriteString(‘DocumentSection’,string(FileID), responseObj.ValidationResults[0].ReasonCode);
result := true;
processingGetFile := false;
end
else // in the middle of receiving pieces of a big file. Save off what we have, ask for more.
begin
if chunkID = 1 then
begin
if FileExists2(DesintationFilePath) then
DeleteFile(DesintationFilePath);
Zipfile := TFileStream.Create(DesintationFilePath,FmOpenReadWrite or FmShareDenyNone or fmCreate);
end;
Zipfile.Position := getFileSize(DesintationFilePath);
DecodedZipfile := DecodeString(responseObj.opsResponseObj.document);
Zipfile.WriteBuffer(Pointer(DecodedZipfile)^, Length(DecodedZipfile));
GetFileInHeader.messageFlowSequence := chunkID;
responseObj := DocSvc.getDocument(GetFileInHeader, GetFileIn);
end;
end;
function getFileSize(path: string): integer;
var
info : TWin32FileAttributeData;
begin
result := -1;
if not GetFileAttributesex(Pchar(path), GetFileExInfoStandard, @info) then
exit;
result := (info.nFileSizeLow or (info.nFileSizeHigh shl 32));
end;
Сложно прочитать код из-за дублирования. Используйте переменные, чтобы избежать повторения одной и той же строки. Разделение кода написания файла на отдельный метод помогло бы. Вам нужно использовать try/finally. 'info.nFileSizeHigh shl 32 = info.nFileSizeHigh'. Перед применением shl вам нужно отправить в Int64. –
Это всего лишь отрывок из всей функции, она сидит в блоке try/except для обработки ошибок и блок try/finally для освобождения ресурсов. Когда возникает проблема не всех данных, поступающих в файл, никаких исключений не возникает. – mcmar
В коде явно отсутствуют блоки. Во всяком случае, дублирование затрудняет чтение. Вы просите об ошибках. –