Uploads a file to the FTP server. This involves both the sending of a PASV command to open the data channel and the upload over the data channel. The data channel is closed after the upload so this function is called for every file required.
| Return Type | Function name | Arguments |
|---|---|---|
| hzEcode | hzFtpClient::FileUpload | (hzString&,hzString&,) |
Declared in file: hzFtpClient.h
Defined in file : hzFtpClient.cpp
Function Logic:
Function body:
hzEcode hzFtpClient::FileUpload (hzString& SvrFilename)hzString& LocFilename,
{
// Uploads a file to the FTP server. This involves both the sending of a PASV command to open the data channel and the upload over the data
// channel. The data channel is closed after the upload so this function is called for every file required.
//
// Arguments: 1) SvrFilename Name file is to be called on the server
// 2) LocFilename Name file has on local machine
//
// Returns: E_NOTFOUND Named file does not exists.
// E_OPENFAIL Named file could not be opened.
// E_PROTOCOL Protocol error.
// E_OK Operation successful, file fully uploaded.
_hzfunc("hzFtpClient::FileDownload") ;
hzTcpClient X ; // TCP client
FSTAT fs ; // File info
ifstream is ; // Target file stream
uint32_t nSize ; // Total bytes to upload (file size)
uint32_t nRecv ; // Bytes in server response
uint32_t nDone = 0; // Bytes uploaded
uint32_t len ; // Command length
uint32_t nTry ; // Reconnections
hzEcode rc ; // Return code
/*
** ** Because the source file is local, first thing we do is check it exists and the size
** */
// X.SetDebug(_hzGlobal_Debug & HZ_DEBUG_CLIENT) ;
if (lstat(*LocFilename, &fs) == -1)
{ threadLog("Failed to locate source file for upload %s\n", *LocFilename) ; return E_NOTFOUND ; }
nSize = fs.st_size ;
rc = OpenInputStrm(is, *LocFilename) ;
if (rc != E_OK)
return rc ;
/*
** ** Now upload the file: Loop round until success
** */
for (nTry = 0; nTry < 2; nTry++)
{
nDone = 0;
if (nTry)
{
X.Close() ;
m_ConnControl.Close() ;
rc = _reconnect() ;
if (rc != E_OK)
break ;
}
// Next step is to open a data channel
rc = _openpasv(X) ;
if (rc != E_OK)
{ threadLog("Failed PASV ... trying again\n") ; continue ; }
// Send the STOR command and recv the response
sprintf(m_c_sbuf, "STOR %s\r\n", *SvrFilename) ;
len = strlen(m_c_sbuf) ;
if ((rc = m_ConnControl.Send(m_c_sbuf, len)) != E_OK)
{ threadLog("Could not send STOR command to upload file %s (attempt %d of 3)\n", *SvrFilename, nTry) ; continue ; }
if ((rc = _ftprecv(nRecv, *_fn)) != E_OK)
{
threadLog("Could not recv STOR response (file=%s, attempt %d of 3)\n", *SvrFilename, nTry) ;
rc = _reconnect() ;
continue ;
}
// Check response code
if (m_nRescode >&eq; 400)
{ threadLog("Got bad STOR response (%d) - aborting\n", m_nRescode) ; rc = E_PROTOCOL ; break ; }
// Then if all is well, upload the file
for (nDone = 0; nDone < nSize && rc == E_OK ; nDone += is.gcount())
{
is.read(m_x_sbuf, HZ_MAXPACKET) ;
if (!is.gcount())
break ;
rc = X.Send(m_x_sbuf, is.gcount()) ;
if (rc != E_OK)
threadLog("No socket during upload of file %s to %s\n", *LocFilename, *SvrFilename) ;
}
// If not OK then retry
if (rc != E_OK)
continue ;
// Otherwise close channel and exit loop
is.close() ;
X.Close() ;
break ;
}
// Get server progress report of upload
if (rc == E_OK)
{
if ((rc = _ftprecv(nRecv, *_fn)) != E_OK)
threadLog("Could not get progress report to STOR command. Giving up (file=%s)\n", *SvrFilename) ;
else
{
if (m_nRescode != 226)
{ threadLog("Expected code of 226 (Xfer complete), got %d\n", m_nRescode) ; rc = E_PROTOCOL ; }
}
}
if (nDone != nSize)
{
threadLog("File size of %d bytes, uploaded %d\n", nSize, nDone) ;
if (rc == E_OK)
rc = E_SENDFAIL ;
}
if (rc != E_OK)
threadLog("Could not upload %s\n\n", *LocFilename) ;
else
{
threadLog("Uploaded %s\n", *LocFilename) ;
m_nTries = 0;
}
return rc ;
}