当使用cURL PHP使HTTP原始POST请求多部分/表单数据时,如何正确设置Content-Length标头


When making HTTP raw POST request multipart/form-data with cURL PHP, how to properly set the Content-Length header?

我有一个关于我需要在PHP中使用curl设置Content-Length标头以发出多部分/表单数据POST HTTP请求的方式的问题。

例如,我有一个PHP脚本,它使curl POST将图像上传到服务器,请求的HTTP实体正文的内容如下所示:

------Boundary123
Content-Disposition: form-data; name="files[]"; filename="image.png"
Content-Type: image/png
... contents of image.png
------Boundary123--

我做这样的事情:

 $bodiEntity = "--".$boundary."'r'n".
               'Content-Disposition: form-data; name="files[]"; filename="'.$fileName.'"'."'r'n".
               'Content-Type: img/png'."'r'n'r'n".
                file_get_contents($fileName)."'r'n". // binary contents of file
                "--".$boundary."--'r'n";

但是,我应该为内容长度标头设置哪个值?我知道,这是实体体的字节数,但是我应该如何处理"''r'"?我的意思是,如果我这样做strlen("'r'n")我会得到 2 作为返回值,但我想在处理发送多部分/表单数据时它应该是 1(意思)一个字节,对吗?

那么我是否应该只对边界字符串、内容处置、内容类型等字符串使用 strlen() 并将"''r'"计数为单个字符,并使用filesize()获取文件的文件大小(以字节为单位),然后对所有值求和以获得内容长度标头的最终值?还是我应该像 PHP 那样将 "''r'" 算作 2 个字符?

感谢您的关注!

将"''r'"计数为两个字节。CRLF 对的长度为两个字节。整个身体包括

 - the boundary prefix ("--"), 
 - boundary, 
 - the content bytes, 
 - the interim boundaries and their prefixes, 
 - the final boundary prefix, 
 - boundary and boundary post fix,

所有这些都应该在内容长度中考虑。

至于内容长度。从 HTTP 1.1 开始,没有为多部分请求中的每个文件部分定义内容长度。

但是,应在请求的开头定义总内容长度标头。您可能希望阅读 RFC 7230 第 3.3.2 节。它是由Web和HTTP标准的主要作者之一Roy Thomas Fielding编写的。

但是还有许多其他方法可以将文件作为请求发送,它不一定需要在基于边界的多部分请求中绑定。POST 方法本身中的另一种机制是原始内容类型请求。内容在标头在请求中结束之后传输,后跟一个空行(读取"''r'")。

其他机制包括 PUT 请求,它们也可以以类似的方式工作。从技术上讲,这两者都有差异,将它们分开,尽管我认为进入这个细节与这个问题没有任何关系,所以我会跳过它。