之前完成公司机动车监测数据上传时,遗留的问题,采集到的视频数据也需要上传到服务器存储。上次调整只把数据库json子串给传过去了,对方平台的也是新开发的,慢慢调试中。
遇到的问题,上传时格式化子串为UTF8格式问题,JSON格式多检查几遍,我这总是不仔细,搞错好几次。完善的平台会返回比较完整的错误信息,方便排查问题。
找了一个网站post在线测试,有需要可以用这个先测试调通,然后对照自己的代码更改,比较方便。
在线POST测试工具
下面是上传视频文件的代码实例:
参数:
strURL, 服务端地址访问接口
csHeaders ,应用中添加需要的请求头数据
strLocalFileName,上传文件的本地路径
BOOL UploadRecFile(LPCTSTR strURL, CString csHeaders,LPCTSTR strLocalFileName)
{
if (strURL == NULL ||
strURL == _T("") ||
strLocalFileName == NULL ||
strLocalFileName == _T("") ||
!PathFileExists(strLocalFileName) ||
PathIsDirectory(strLocalFileName))
{
return FALSE;
}
CHttpFile *pHttpFile = NULL;
CHttpConnection* connection = NULL;
CInternetSession session(_T("UploadFile"));
DWORD dwType;
INTERNET_PORT nPort;
CString strServer, strObject;
if (!AfxParseURL(strURL, dwType, strServer, strObject, nPort))
return FALSE;
BOOL bSuccess = FALSE;
DWORD dwReadLength;
DWORD dwResponseLength;
DWORD dwTotalRequestLength;
const DWORD dwChunkLength = 1024;
char pBuffer[dwChunkLength];
memset(pBuffer, 0, dwChunkLength);
try
{
connection = session.GetHttpConnection(strServer, nPort);
pHttpFile = connection->OpenRequest(CHttpConnection::HTTP_VERB_POST, strObject);
CTime ct;
CString strTime, strBoundary;
ct = CTime::GetCurrentTime();
strTime = ct.Format(_T("%Y%m%d%H%M%S"));
// strBoundary 这个字符串,随意更改即可,主要是界定字段数据的
strBoundary = _T("*-*-*") + strTime + _T("*-*-*");
CString strPreFileHeaders;
// 这里添加了一个csHeaders,平台定义了一个包含token的验证子串,在这里添加
strPreFileHeaders.Format(_T("Content-Type: multipart/form-data;boundary=%s\r\n%s\r\n"), strBoundary, csHeaders);
pHttpFile->AddRequestHeaders(strPreFileHeaders);
CString strPostData, csLocalFilename;
csLocalFilename = strLocalFileName;
int nPos = csLocalFilename.ReverseFind('/');
CString strFileName = csLocalFilename.Mid(nPos + 1);
m_md5.update(strFileName.GetBuffer());
CString sqlvalue = m_md5.toString().c_str();
m_md5.reset();
// 找了一个UTF8-ANSI互转的函数,正常服务端和应用端定义格式都是UTF8
strPostData.Format(_T("--%s\r\nContent-Disposition: form-data; name =\"file\"; filename=\"%s.mp4\"\r\n\r\n"), strBoundary, UTF8Convert(sqlvalue, CP_ACP, CP_UTF8));
CString endPostData;
endPostData.Format(_T("\r\n--%s--\r\n"), strBoundary);
CFile file;
file.Open(strLocalFileName, CFile::shareDenyNone | CFile::modeRead);
DWORD sendLength = strPostData.GetLength() + endPostData.GetLength() + file.GetLength();
pHttpFile->SendRequestEx(sendLength, HSR_SYNC | HSR_INITIATE);
pHttpFile->Write((LPSTR)(LPCTSTR)strPostData, strPostData.GetLength());
dwReadLength = -1;
while (0 != dwReadLength)
{
dwReadLength = file.Read(pBuffer, dwChunkLength);
if (dwReadLength > 0)
{
pHttpFile->Write(pBuffer, dwReadLength);
}
}
file.Close();
pHttpFile->Write((LPSTR)(LPCTSTR)endPostData, endPostData.GetLength());
pHttpFile->EndRequest();
DWORD dwStauts;
if (!pHttpFile->QueryInfoStatusCode(dwStauts) || dwStauts < 200 || 299 < dwStauts)
{
bSuccess = FALSE;
}
else
{
CString response, text;
for (int i = 0; pHttpFile->ReadString(text); ++i)
{
response += UTF8Convert(text, CP_UTF8, CP_ACP) + "\r\n";
}
// 返回信息包含文件上传后的新地址,需要在后续的数据库JSON子串中用到,定义了全局变量
m_csNewFileName = response.Mid(response.Find("\"fileName\":\"") + 12);
m_csNewFileName = m_csNewFileName.Mid(0, m_csNewFileName.Find("\",\"code\":"));
bSuccess = TRUE;
}
}
catch (CInternetException * pEx)
{
char sz[256];
pEx->GetErrorMessage(sz, 25);
CString str;
str.Format("InternetException occur:%s", sz);
bSuccess = FALSE;
}
catch (...)
{
bSuccess = FALSE;
}
if (pHttpFile != NULL)
{
pHttpFile->Close();
pHttpFile = NULL;
}
if (connection != NULL)
{
connection->Close();
connection = NULL;
}
session.Close();
return bSuccess;
}
子串互转的代码,也贴到这了,UTF8和ANSI可以互转。
返回值为cstring,想要得到的格式子串。
CString UTF8Convert(CString &str, int sourceCodepage, int targetCodepage)
{
//CP_ACP=ANSI,CP_UTF8=utf-8
int len = str.GetLength();
int unicodeLen = MultiByteToWideChar(sourceCodepage, 0, str, -1, NULL, 0);
wchar_t * pUnicode;
pUnicode = new wchar_t[unicodeLen + 1];
memset(pUnicode, 0, (unicodeLen + 1)*sizeof(wchar_t));
MultiByteToWideChar(sourceCodepage, 0, str, -1, (LPWSTR)pUnicode, unicodeLen);
BYTE * pTargetData = nullptr;
int targetLen = WideCharToMultiByte(targetCodepage, 0, (LPWSTR)pUnicode, -1, (char *)pTargetData, 0, NULL, NULL);
pTargetData = new BYTE[targetLen + 1];
memset(pTargetData, 0, targetLen + 1);
WideCharToMultiByte(targetCodepage, 0, (LPWSTR)pUnicode, -1, (char *)pTargetData, targetLen, NULL, NULL);
CString rt;
rt.Format("%s", pTargetData);
delete pUnicode;
delete pTargetData;
return rt;
}