Reputation: 1790
I am trying to upload a file using MFC C++ but for some reason i am getting invalid file on the upload. I feels like maybe this is the problem due to wrong header or post information i am using but after several hours tries i cant find my error. Here is my code.. I will appreciate if you experts can elaborate some light on my mistakes so i can correct it...
void CFileUpload::UploadByPost(CString strFileName,CString strServerUrl,CString strServerUploadFile)
{
DWORD dwTotalRequestLength;
DWORD dwChunkLength;
DWORD dwReadLength;
DWORD dwResponseLength;
CHttpFile* pHTTP = NULL;
dwChunkLength = 64 * 1024;
void* pBuffer = malloc(dwChunkLength);
CFile file ;
if (!file.Open(strFileName.GetBuffer(),
CFile::modeRead | CFile::shareDenyWrite))
{
return;
}
CInternetSession session(L"sendFile");
CHttpConnection *connection = NULL;
try
{
//Create the multi-part form data that goes before and after the actual file upload.
CString strHTTPBoundary = _T("FFF3F395A90B452BB8BEDC878DDBD152");
CString strPreFileData = MakePreFileData(strHTTPBoundary, file.GetFileName());
CString strPostFileData = MakePostFileData(strHTTPBoundary);
CString strRequestHeaders = MakeRequestHeaders(strHTTPBoundary);
dwTotalRequestLength = strPreFileData.GetLength() + strPostFileData.GetLength() + file.GetLength();
connection = session.GetHttpConnection(/*L"www.YOURSITE.com"*/strServerUrl.GetBuffer(),NULL,INTERNET_DEFAULT_HTTP_PORT);
pHTTP = connection->OpenRequest(CHttpConnection::HTTP_VERB_POST, strServerUploadFile.GetBuffer());//_T("/YOUURL/submit_file.pl"));
pHTTP->AddRequestHeaders(strRequestHeaders);
pHTTP->SendRequestEx(dwTotalRequestLength, HSR_SYNC | HSR_INITIATE);
//Write out the headers and the form variables
pHTTP->Write((LPSTR)(LPCSTR)strPreFileData.GetBuffer(), strPreFileData.GetLength());
//upload the file.
dwReadLength = -1;
int length = file.GetLength(); //used to calculate percentage complete.
while (0 != dwReadLength)
{
dwReadLength = file.Read(pBuffer, dwChunkLength);
if (0 != dwReadLength)
{
pHTTP->Write(pBuffer, dwReadLength);
}
}
file.Close();
//Finish the upload.
pHTTP->Write((LPSTR)(LPCSTR)strPostFileData.GetBuffer(), strPostFileData.GetLength());
pHTTP->EndRequest(HSR_SYNC);
//get the response from the server.
LPSTR szResponse;
CString strResponse;
dwResponseLength = pHTTP->GetLength();
while (0 != dwResponseLength )
{
szResponse = (LPSTR)malloc(dwResponseLength + 1);
szResponse[dwResponseLength] = '\0';
pHTTP->Read(szResponse, dwResponseLength);
strResponse += szResponse;
free(szResponse);
dwResponseLength = pHTTP->GetLength();
}
TRACE(L"%s",strResponse.GetBuffer());
//close everything up.
pHTTP->Close();
connection->Close();
session.Close();
}
catch(CInternetException* e)
{
TRACE(L"error: %d \n",e->m_dwError);
}
catch(CFileException* e)
{
TRACE(L"error: %d \n",e->m_cause);
}
catch(...)
{
TRACE(L" unexpected error");
}
}
here is my header and post function
CString CFileUpload::MakeRequestHeaders(CString& strBoundary)
{
CString strFormat;
CString strData;
strFormat = _T("Content-Type: multipart/form-data; boundary=%s\r\n");
strData.Format(strFormat, strBoundary);
return strData;
}
CString CFileUpload::MakePreFileData(CString& strBoundary, CString& strFileName)
{
CString strFormat;
CString strData;
strFormat += _T("--%s");
strFormat += _T("\r\n");
strFormat += _T("Content-Disposition: form-data; name=\"file\"; filename=\"%s\"");
strFormat += _T("\r\n");
strFormat += _T("Content-Type: text/plain");
strFormat += _T("\r\n");
strFormat += _T(" XXXXX ");
strFormat += _T("\r\n\r\n");
strData.Format(strFormat, strBoundary,/* m_Name, strBoundary,*/ strFileName);
return strData;
}
CString CFileUpload::MakePostFileData(CString& strBoundary)
{
CString strFormat;
CString strData;
strFormat = _T("\r\n");
strFormat += _T("--%s");
strFormat += _T("\r\n");
strFormat += _T("Content-Disposition: form-data; name=\"submit\"");
strFormat += _T("\r\n\r\n");
strFormat += _T("");
strFormat += _T("\r\n");
strFormat += _T("--%s--");
strFormat += _T("\r\n");
strData.Format(strFormat, strBoundary, strBoundary);
return strData;
}
It always return invalid file, the file server code i am using is the following
<?php
$allowedExts = array("log", "txt");
$extension = end(explode(".", $_FILES["file"]["name"]));
if ((($_FILES["file"]["type"] == "text/plain")
)
&& ($_FILES["file"]["size"] < 20000)
&& in_array($extension, $allowedExts))
{
if ($_FILES["file"]["error"] > 0)
{
echo "Error: " . $_FILES["file"]["error"] . "<br>";
}
else
{
echo "Upload: " . $_FILES["file"]["name"] . "<br>";
echo "Type: " . $_FILES["file"]["type"] . "<br>";
echo "Size: " . ($_FILES["file"]["size"] / 1024) . " kB<br>";
echo "Stored in: " . $_FILES["file"]["tmp_name"];
}
}
else
{
echo "Invalid file";
}
?>
and here is the form
<html>
<body>
<form action="upload_file.php" method="post"
enctype="multipart/form-data">
<label for="file">Filename:</label>
<input type="file" name="file" id="file"><br>
<input type="submit" name="submit" value="Submit">
</form>
</body>
</html>
Note:- i cant use boost or poco, curl or any third party library.. just only win32 or mfc.
here are the pre make and post make data :
header
"Content-Type: multipart/form-data; boundary=FFF3F395A90B452BB8BEDC878DDBD152
"
Pre File
"--FFF3F395A90B452BB8BEDC878DDBD152
Content-Disposition: form-data; name="Filename"; filename="ddd.txt"
Content-Type: text/plain
Content-Transfer-Encoding: binary
"
Post File
"
--FFF3F395A90B452BB8BEDC878DDBD152
Content-Disposition: form-data; name="submit" value="submit"
--FFF3F395A90B452BB8BEDC878DDBD152--
"
Upvotes: 1
Views: 2639
Reputation: 1790
Finally i got the error.... this is not because of the post or pre file data or headeror server script but because the way i was calling write function from http object and converting the unicode to ansi without any proper conversion....I dont know how come i didn't realize this silly mistake by me lol...but for the sake of others i would like to share this information as well.....
pHTTP->Write((LPSTR)(LPCSTR)strPreFileData.GetBuffer(), strPreFileData.GetLength());
must be change to
pHTTP->Write((LPSTR)(LPCSTR)CW2A(strPreFileData.GetBuffer()), strPreFileData.GetLength());
Also the post file version
pHTTP->Write((LPSTR)(LPCSTR)strPostFileData.GetBuffer(), strPostFileData.GetLength());
to
pHTTP->Write((LPSTR)(LPCSTR)CW2A(strPostFileData.GetBuffer()), strPostFileData.GetLength());
Upvotes: 1
Reputation: 19632
Well there are three cases in your server-side code that could have gone wrong:
if ((($_FILES["file"]["type"] == "text/plain")
)
&& ($_FILES["file"]["size"] < 20000)
&& in_array($extension, $allowedExts))
Apart from the hideous indentation and brace placement, have you tried testing for each condition separately so that you know what exactly the php parts thinks is wrong?
[mistake has been removed]
Upvotes: 0