本例将完成一个mfc程序上传图片至服务端接收(php)的实例,以下是具体步骤:
1.新建一个dialog(本例UpLoadFile.exe)
添加完成上传功能的方法:(头文件申明以下省略)
#include <afxinet.h> //CHttpFile
const CString SERVER = L"127.0.0.1";
const CString SERVER_SITE = L"/upload.php";
CString CUpLoadFileDlg::UpLoadFile(CString strFile,CString strServer,CString strServerSite)
{
DWORD dwTotalRequestLength;
DWORD dwChunkLength;
DWORD dwReadLength;
DWORD dwResponseLength;
CHttpFile* pHttp = NULL;
dwChunkLength = 64 * 1024;
void* pBuffer = malloc(dwChunkLength);
CFile file;
if (!file.Open(strFile.GetBuffer(), CFile::modeRead | CFile::shareDenyWrite))
{
return L"file error";
}
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();
//port
connection = session.GetHttpConnection(/*L"www.YOURSITE.com"*/strServer.GetBuffer(),NULL,INTERNET_DEFAULT_HTTP_PORT); //默认服务端80端口
//post/get
pHttp = connection->OpenRequest(CHttpConnection::HTTP_VERB_POST, strServerSite.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)CW2A(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)CW2A(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();
}
//close everything up.
pHttp->Close();
connection->Close();
session.Close();
return strResponse;
}
catch(CInternetException *pEx)
{
return L"upload error";
}
}
CString CUpLoadFileDlg::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 CUpLoadFileDlg::MakePreFileData(CString& strBoundary, CString& strFileName)
{
CString strFormat;
CString strData;
strFormat += _T("--%s");
strFormat += _T("\r\n");
strFormat += _T("Content-Disposition: form-data; name=\"pic\"; filename=\"%s\""); //name接收端$_FILES['pic']
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, strFileName);
return strData;
}
CString CUpLoadFileDlg::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;
}
除了上传功能,还需要用到选择文件的功能,修改界面如下:
完成文件选择的相关操作:
//返回选择的文件名称
CString CUpLoadFileDlg::BootOpenDialog()
{
CString strFile = _T("");
CFileDialog dlgFile(true, NULL, NULL, OFN_HIDEREADONLY, _T("IMG Files (*.jpg)|*.jpg|GIF Files (*.gif)|*.gif|All Files (*.*)|*.*||"), NULL);
if (dlgFile.DoModal())
{
strFile = dlgFile.GetPathName();
}
return strFile;
}
//浏览按钮
void CUpLoadFileDlg::OnBnClickedButton1()
{
// TODO: 在此添加控件通知处理程序代码
CEdit* pEdit;
pEdit = (CEdit*) GetDlgItem(IDC_EDIT1);
CString strFile = this->BootOpenDialog();
pEdit->SetWindowTextW(strFile);
}
//上传按钮
void CUpLoadFileDlg::OnBnClickedButton2()
{
// TODO: 在此添加控件通知处理程序代码
CEdit* pEdit;
pEdit = (CEdit*) GetDlgItem(IDC_EDIT1);
CString strFile;
pEdit->GetWindowTextW(strFile);
pEdit->SetWindowTextW(UpLoadFile(strFile, SERVER, SERVER_SITE));
}
2.接收上传的服务端完成一个上传页面(本例用php完成):
upload.php:
<?php
if(isset($_FILES['pic']))
{
$path = 'pic/';
if(!file_exists($path))
{
mkdir($path, 0777);
}
move_uploaded_file($_FILES['pic']['tmp_name'], $path.strtotime('now').$_FILES['pic']['name']);
echo 'upload complete';
}
else
{
echo 'upload error';
}
?>
编译运行,上传图片测试: