PDA

View Full Version : ftp transfer corruption



tux
24-06-2004, 01:53 AM
ive created my own code to transfer files to and from a ftp server. the read code works ok so i turned it into write code, it uploads ok but when i re download the file with my normal ftp app its all corrupted (but the end of the exe file i tryed seems ok).

heres the code for read and write.


function DownloadFTP(strHost, strUsername, strPassword, strRemoteDir, strRemoteFile, strLocalFile: String; iPort: Integer;
ProgressBar: TProgressBar): Integer;
const
iBuffReadSize= 4096;

var
fLocalFile: File;
hNet: hInternet;
hFTP: hInternet;
hRemoteFile: hInternet;
sRec: TWin32FindData;
iFileSize, iBuffSize, iBytesRead: DWord;
arrBuffer: Array[0..iBuffReadSize -1] of Byte;

Begin
if not (strHost = '') or (strUsername = '') or (strRemoteDir = '') or (strRemoteFile = '') or (strLocalFile = '') then
Begin
hNet := InternetOpen(PChar(Application.Title), INTERNET_OPEN_TYPE_PRECONFIG, '', '', 0);

if Assigned(hNet) then
Begin
hFTP := InternetConnect(hNet, PChar(strHost), iPort, PChar(strUserName), PChar(strPassword), INTERNET_SERVICE_FTP, 0, 0);

if Assigned(hFTP) then
Begin
if FtpSetCurrentDirectory(hFTP, PChar(strRemoteDir)) then
Begin
if FtpFindFirstFile&#40;hFTP, PChar&#40;strRemoteFile&#41;, sRec, 0, 0&#41; <> nil then // find the file size
Begin
iFileSize &#58;= sRec.nFileSizeLow;
ProgressBar.Max &#58;= iFileSize;

hRemoteFile &#58;= FTPOpenFile&#40;hFTP, PChar&#40;strRemoteFile&#41;, GENERIC_READ, FTP_TRANSFER_TYPE_BINARY, 0&#41;;

if Assigned&#40;hRemoteFile&#41; then
Begin
AssignFile&#40;fLocalFile, strLocalFile&#41;;
ReWrite&#40;fLocalFile, 1&#41;;

iBuffSize &#58;= iBuffReadSize;
iBytesRead &#58;= 0;

while iBuffSize > 0 do
Begin
if not InternetReadFile&#40;hRemoteFile, @arrBuffer, iBuffReadSize, iBuffSize&#41; then
Begin
Result &#58;= -7; // error reading file
Break;
end;

if &#40;iBuffSize > 0&#41; and &#40;iBuffSize <= iBuffReadSize&#41; then
BlockWrite&#40;fLocalFile, arrBuffer&#91;0&#93;, iBuffSize&#41;
else
Result &#58;= 1; // reached end of file

iBytesRead &#58;= iBytesRead + iBuffSize;
ProgressBar.Position &#58;= iBytesRead;
Application.ProcessMessages;
end;

CloseFile&#40;fLocalFile&#41;;
InternetCloseHandle&#40;hRemoteFile&#41;;
end
else
Result &#58;= -6; // error opening remote file
end
else
Result &#58;= -5; // cannot find the file to download
end
else
Result &#58;= -4; // cannot change directory

InternetCloseHandle&#40;hFTP&#41;;
end
else
Result &#58;= -3; // host unnavailible

InternetCloseHandle&#40;hNet&#41;;
end
else
Result &#58;= -2; // unable to access WinInet.dll
end
else
Result &#58;= -1; // empty connection strings
end;

function UploadFTP&#40;strHost, strUsername, strPassword, strRemoteDir, strRemoteFile, strLocalFile&#58; String; iPort&#58; Integer;
ProgressBar&#58; TProgressBar&#41;&#58; Integer;
var
fLocalFile&#58; File;
hNet&#58; hInternet;
hFTP&#58; hInternet;
hRemoteFile&#58; hInternet;
iFileSize&#58; DWord;
iBuffSize&#58; DWord;
iBytesWritten&#58; DWord;
iBuffWriteSize&#58; DWord;
arrBuffer&#58; Array of Byte;
sRec&#58; TWin32FindData;

Begin
iBuffWriteSize &#58;= 4096;
SetLength&#40;arrBuffer, iBuffWriteSize -1&#41;;

if not &#40;strHost = ''&#41; or &#40;strUsername = ''&#41; or &#40;strRemoteDir = ''&#41; or &#40;strRemoteFile = ''&#41; or &#40;strLocalFile = ''&#41; then
Begin
hNet &#58;= InternetOpen&#40;PChar&#40;Application.Title&#41;, INTERNET_OPEN_TYPE_PRECONFIG, '', '', 0&#41;;

if Assigned&#40;hNet&#41; then
Begin
hFTP &#58;= InternetConnect&#40;hNet, PChar&#40;strHost&#41;, iPort, PChar&#40;strUserName&#41;, PChar&#40;strPassword&#41;, INTERNET_SERVICE_FTP, 0, 0&#41;;

if Assigned&#40;hFTP&#41; then
Begin
if FtpSetCurrentDirectory&#40;hFTP, PChar&#40;strRemoteDir&#41;&#41; then
Begin
if FtpFindFirstFile&#40;hFTP, PChar&#40;strRemoteFile&#41;, sRec, 0, 0&#41; <> nil then // see if the file exists
Begin
FtpDeleteFile&#40;hFTP, PChar&#40;strRemoteFile&#41;&#41;;
end;

if FileExists&#40;strLocalFile&#41; then
Begin
hRemoteFile &#58;= FtpOpenFile&#40;hFTP, PChar&#40;strRemoteFile&#41;, GENERIC_WRITE, FTP_TRANSFER_TYPE_BINARY, 0&#41;;

if Assigned&#40;hRemoteFile&#41; then
Begin
AssignFile&#40;fLocalFile, strLocalFile&#41;;
Reset&#40;fLocalFile, 1&#41;;

iFileSize &#58;= FileSize&#40;fLocalFile&#41;;
ProgressBar.Max &#58;= iFileSize;

iBuffSize &#58;= iBuffWriteSize;
iBytesWritten &#58;= 0;

while iBuffSize > 0 do
Begin
if iFileSize - iBytesWritten < iBuffWriteSize then
Begin
SetLength&#40;arrBuffer, iFileSize - iBytesWritten&#41;;
iBuffWriteSize &#58;= iFileSize - iBytesWritten;
end;

BlockRead&#40;fLocalFile, arrBuffer&#91;0&#93;, iBuffWriteSize&#41;;

if &#40;iBuffSize > 0&#41; and &#40;iBuffSize <= iBuffWriteSize&#41; then
if not InternetWriteFile&#40;hRemoteFile, @arrBuffer, iBuffWriteSize, iBuffSize&#41; then
Begin
Result &#58;= -7; // error writing file
Break;
end
else
else
Begin
Result &#58;= 1; // end of file
Break;
end;

iBytesWritten &#58;= iBytesWritten + iBuffSize;

ProgressBar.Position &#58;= iBytesWritten;
Application.ProcessMessages;
end;

CloseFile&#40;fLocalFile&#41;;
InternetCloseHandle&#40;hRemoteFile&#41;;
end
else
Result &#58;= -6; // error opening remote file
end
else
Result &#58;= -5; // cannot find the file to download
end
else
Result &#58;= -4; // cannot change directory

InternetCloseHandle&#40;hFTP&#41;;
end
else
Result &#58;= -3; // host unnavailible

InternetCloseHandle&#40;hNet&#41;;
end
else
Result &#58;= -2; // unable to access WinInet.dll
end
else
Result &#58;= -1; // empty connection strings
end;

its probably just something simple. anyone have any ideas why?

cairnswm
24-06-2004, 05:14 AM
Thats what idFTP is for :)

Aldor
24-06-2004, 02:18 PM
I think nobody will "compile in head" so big piece of code. Try to split it or to replace some code by description.

And write your "uses" section. For example, what is "hInternet"? Where did you get it?

And then, probably, it would be easier to answer your question.

tux
24-06-2004, 03:24 PM
uses WinInet, ComCtrls, Forms, Windows, SysUtils;


while iBuffSize > 0 do
Begin
if iFileSize - iBytesWritten < iBuffWriteSize then
Begin
SetLength&#40;arrBuffer, iFileSize - iBytesWritten&#41;;
iBuffWriteSize &#58;= iFileSize - iBytesWritten;
end;

BlockRead&#40;fLocalFile, arrBuffer&#91;0&#93;, iBuffWriteSize&#41;;

if &#40;iBuffSize > 0&#41; and &#40;iBuffSize <= iBuffWriteSize&#41; then
if not InternetWriteFile&#40;hRemoteFile, @arrBuffer, iBuffWriteSize, iBuffSize&#41; then
Begin
Result &#58;= -7; // error writing file
Break;
end
else
else
Begin
Result &#58;= 1; // end of file
Break;
end;

iBytesWritten &#58;= iBytesWritten + iBuffSize;

ProgressBar.Position &#58;= iBytesWritten;
Application.ProcessMessages;
end;

thats probably the bit u need to focus on :) and i dont want to use components to do this for me :P

tux
25-06-2004, 12:08 PM
anyone? :o

Paulius
25-06-2004, 01:28 PM
Can't spot any obvious problem, try uploading a small file and comparing it to the original with a hex editor to get a hint where and in what way it gets corrupted.

tux
25-06-2004, 03:02 PM
ive done some more searching and have come to the conclusion that im confused :o

http://www.deviousdevelopment.com/skin.ini is teh origional
http://www.deviousdevelopment.com/skin1.ini is after the upload.


i put a breakpoint on the internetwrite procedure and the data buffer going to the procedure is NOT corrupt. so its somehow getting corrupted on its way through the internet.

the download code does NOT corrupt it, so im really confused now :(

tux
27-06-2004, 12:36 AM
its fixed

Paulius
27-06-2004, 08:22 AM
So what was the problem?

tux
27-06-2004, 01:09 PM
if not InternetWriteFile&#40;hRemoteFile, @arrBuffer, iBuffWriteSize, iBuffSize&#41; then

had to be


if not InternetWriteFile&#40;hRemoteFile, Pointer&#40;arrBuffer&#41;, iBuffWriteSize, iBuffSize&#41; then