当前位置:首页 > Windows程序 > 正文

达到HTTP合约Get、Post和文件上传功能

2021-03-25 Windows程序

于《采用WinHttp实现HTTP协议Get、Post和文件上传功能》一文中,我已经比較具体地解说了怎样使用WinHttp接口实现各种协议。

在近期的代码梳理中,我认为Post和文件上传模块能够得到简化,于是差点儿重写了这两个功能的代码。由于Get、Post和文件上传功能的基础(父)类基本没有修改,函数调用的流程也基本没有变化,所以本文我将重点解说修改点。

(转载请指明出于breaksoftware的csdn博客)

首先我改动了接口的字符集。之前我都是使用UNICODE作为接口參数类型,当中一个原因是Windows提倡UNICODE编码,其次是由于WinHttp接口仅仅提供了UNICODE接口函数。而我在本次改动中,将字符集改成UTF8。由于在网络传输方便,UTF8格式才是主流。

于是为了使用WinHttp接口,我提供了一个A版本号的转换层——project中WinhttpA.h。

其次。我增强了Post接口。《使用WinHttp接口实现HTTP协议Get、Post和文件上传功能》的读者和我讨论了非常多Post协议,让我感觉非常有必要重视起该功能。本文我们将着重解说Post的实现和測试。

再次,我将Post的实现和文件上传功能的实现合二为一。由于两者代码非常相似。事实上在原理方面也是非常相似的。

最后。我使用前一篇博文中介绍的IMemFileOperation接口,又一次定义了Post和文件上传功能的參数定义。由于IMemFileOperation的特性,我们能够上传文件,或者上传一片内存值,或者上传文件里的内容,而这些操作是同样的。

Get请求没什么好说的了。我们主要关注Post和文件上传。

普通情况下,我们遇到的是“我们须要向:8080/yyyy/zzz地址Post数据”。当中的“数据”是我们问题的重点。可能非常多人觉得Post请求就是将全部參数都Post到server,,事实上不然。打个比方。比方我们要求对?

a=b&c=d地址Post一个数据e=f,我们并非将"a=b&c=d&e=f"Post到server,而仅仅是"e=f"Post过去,"a=b&c=d"还是按Get的方式发送。于是我对上一版的设计做了改良,废掉了ParseParams函数。简化了设计,可是要求用户传进来的URL中不包括须要Post过去的数据——须要Post的数据通过SetPostParam方法传递进来。我们想把重点发到这样的发送分离的实现上:

if ( !WinHttpCrackUrlA_( m_strUrl, strHost, strPath, strExt, nPort ) ) { break; } m_hSession = WinHttpOpenA( m_strAgent.empty() ?

NULL : m_strAgent.c_str(), WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0 ); if ( NULL == m_hSession ) { break; } if ( FALSE == WinHttpSetTimeouts(m_hSession, m_nResolveTimeout, m_nConnectTimeout, m_nSendTimeout, m_nSendTimeout) ) { break; } m_hConnect = WinHttpConnectA( m_hSession, strHost.c_str(), nPort, 0 ); if ( NULL == m_hConnect ) { break; } m_strRequestData = strPath + strExt;

主要关注最后一行,我将URL路径和URL參数放到m_strRequestData里。

之后

VOID CHttpRequestByWinHttp::TransmiteDataToServerByPost() { BOOL bSuc = FALSE; do { m_hRequest = WinHttpOpenRequestA(m_hConnect, "Post", m_strRequestData.c_str(), NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, 0); if ( NULL == m_hRequest ) { break; }

这样。我们便将不须要Post的数据发送了过去。

如今我们再探讨下须要Post过去的数据。

首先我们须要明白下数据的来源:

内存中的数据

文件里的数据

无论数据来源于何处。它都能够成为待Post过去的数据或者待上传的文件的内容。

于是我们借用上一篇博文中的IMemFileOperation接口,定义Post的数据的格式。

typedef struct _FMParam_ { std::string strkey; ToolsInterface::LPIMemFileOperation value; bool postasfile; struct FileInfo { char szfilename[128]; }; struct MemInfo{ bool bMulti; }; union { FileInfo fileinfo; MemInfo meminfo; }; }FMParam, *PFMParam; typedef std::vector<FMParam> FMParams; typedef FMParams::iterator FMParamsIter; typedef FMParams::const_iterator FMParamsCIter;        无论是Post数据还是要上传文件,协议中都须要key的存在。strkey是数据的key。

value字段仅仅是一个指针,它是指向一个文件还是内存。已经没有关系了。由于之后我们将使用统一的接口去訪问它。postasfile字段是标志该參数是否以文件内容的形式Post上去。

这儿须要特别说明下,postasfile和value是内存还是文件是没有关系的。

由于value仅仅是指向了数据内容,至于内容上传到server是作为文件的内容还是仅仅是普通Post的数据值是由postasfile决定的。假设postasfile为真。则FileInfo将被利用到。由于它标记了内容上传到server后,server上保存的文件名称。

假设postasfile为假。则我们须要考虑下数据是作为普通数据post,还是作为MultiPart数据Post。这个就取决于MemInfo中的字段了。

至于什么是MultiPart类型,能够简单參考《使用WinHttp接口实现HTTP协议Get、Post和文件上传功能》后半部分关于文件上传的讨论。


对于待上传的数据,之前设计改框架时。框架提供了GetData方法,让继承类提供数据。

温馨提示: 本文由Jm博客推荐,转载请保留链接: https://www.jmwww.net/file/67480.html