tags:

views:

1487

answers:

6

How would I upload a file to a webserver using c++ and MFC. We are not using .Net. Would I need to open a socket and do everything myself? If so, where is a good reference to follow?

+3  A: 

You don't want to use direct socket calls. It's hard to get HTTP right this way.

The easier way is to the WinINet APIs. Check out the docs for InternetOpen, this will likely be the first call you make. Functions you will likely need:

  • InternetOpen
  • InternetConnect
  • HttpOpenRequest
  • HttpSendRequest
  • HttpQueryInfo
  • InternetCloseHandle

You can find docs for all of these on msdn

A: 

You could use BITS:

http://www.codeproject.com/KB/IP/bitsman.aspx

fryguybob
A: 

You can also use XMLHTTP. Even if you aren't sending XML. Built on WinINet, but a bit easier to use (if you're used to working with COM anyway).
See MSDN: http://msdn.microsoft.com/en-us/library/ms759148.aspx

Shog9
+1  A: 

WinInet as suggested. Bear in mind that there are MFC classes that wrap these APIs. If for some reason these APIs aren't flexible engouh for your requirements (e.g. you need to implement connection through a proxy including authentication), give a look at WinHTTP. It's a superset of WinInet (no MFC wrappers though for WinHTTP).

Serge - appTranslator
A: 

If you have an ftp server, check out the CFtpConnection class.

djeidot
I need more then the file. I also need some user entered fields.
Jon Drnek
A: 

Here is the code I ended up using. I stripped out the error checking, and other notification stuff. This does a multi-part form upload.

DWORD dwTotalRequestLength;
DWORD dwChunkLength;
DWORD dwReadLength;
DWORD dwResponseLength;
CHttpFile* pHTTP = NULL;

dwChunkLength = 64 * 1024; 
void* pBuffer = malloc(dwChunkLength);
CFile file ;

CInternetSession session("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("www.YOURSITE.com",NULL,INTERNET_DEFAULT_HTTP_PORT);

pHTTP = connection->OpenRequest(CHttpConnection::HTTP_VERB_POST, _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, 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, 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();
}

AfxMessageBox(strResponse);

//close everything up.
pHTTP->Close();
connection->Close();
session.Close();

CString CHelpRequestUpload::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 CHelpRequestUpload::MakePreFileData(CString& strBoundary, CString& strFileName)
{
CString strFormat;
CString strData;

strFormat = _T("--%s");
strFormat += _T("\r\n");
strFormat += _T("Content-Disposition: form-data; name=\"user\"");
strFormat += _T("\r\n\r\n");
strFormat += _T("%s");
strFormat += _T("\r\n");

strFormat += _T("--%s");
strFormat += _T("\r\n");
strFormat += _T("Content-Disposition: form-data; name=\"email\"");
strFormat += _T("\r\n\r\n");
strFormat += _T("%s");
strFormat += _T("\r\n");

strFormat += _T("--%s");
strFormat += _T("\r\n");
strFormat += _T("Content-Disposition: form-data; name=\"filename\"; filename=\"%s\"");
strFormat += _T("\r\n");
strFormat += _T("Content-Type: audio/x-flac");
strFormat += _T("\r\n");
strFormat += _T("Content-Transfer-Encoding: binary");
strFormat += _T("\r\n\r\n");

strData.Format(strFormat, strBoundary, m_Name, strBoundary, m_Email,  strBoundary, strFileName);

return strData;
 }

CString CHelpRequestUpload::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=\"submitted\"");
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;

}
Jon Drnek