Вопрос

Как мне загрузить файл на веб-сервер, используя C++ и MFC.Мы не используем .Net.Придется ли мне открывать розетку и делать все самому?Если да, то где можно найти хорошую ссылку?

Это было полезно?

Решение

Вы не хотите использовать прямые вызовы сокетов.Таким способом сложно правильно реализовать HTTP.

Более простой способ — использовать API-интерфейсы WinINet.Ознакомьтесь с документацией InternetOpen, скорее всего, это будет ваш первый звонок.Функции, которые вам, вероятно, понадобятся:

  • ИнтернетОткрытый
  • ИнтернетКоннект
  • HttpOpenRequest
  • HttpSendRequest
  • HttpQueryInfo
  • ИнтернетЗакрытьРучка

Вы можете найти документацию по всем этим вопросам на msdn.

Другие советы

Вот код, который я в итоге использовал.Я удалил проверку ошибок и другие уведомления.Это выполняет загрузку формы, состоящей из нескольких частей.

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;

} 

WinInet, как было предложено.Имейте в виду, что существуют классы MFC, которые обертывают эти API.Если по какой-то причине эти API не соответствуют вашим требованиям (например,вам нужно реализовать подключение через прокси, включая аутентификацию), взгляните на WinHTTP.Это расширенный набор WinInet (хотя для WinHTTP нет оболочек MFC).

Вы можете использовать BITS:

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

Вы также можете использовать XMLHTTP.Даже если вы не отправляете XML.Построен на базе WinINet, но немного проще в использовании (если вы все равно привыкли работать с COM).
См. MSDN: http://msdn.microsoft.com/en-us/library/ms759148.aspx

Если у вас есть ftp-сервер, ознакомьтесь с классом CFtpConnection.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top