我正在尝试使用HttpWebRequest
向Web API发送Multipart请求。我发送的请求格式如下:
----------636194206488346738
Content-Disposition: form-data; name="file"; filename="A.png"
Content-Type:application/octet-stream
Content-Transfer-Encoding: binary
{Binary data in here}
----------636194206488346738--
{new line at the end}
请求配置如下:
Content-Type:"multipart/form-data; boundary=----------636194206488346738
Method: POST
Keep-Alive: True
将请求发送到Web API时,我得到了Invalid end of stream error
。但是,我尝试将流转换为文本以查看实际数据,它与我上面添加的示例相匹配。
然而,当我使用WebClient
并为同一目的调用UploadFile
方法时,我可以成功地将文件上传到API而没有任何问题表明我的方法有问题如下。
我的常数:
Boundary = DateTime.Now.Ticks.ToString();
ContentType = "multipart/form-data; boundary=" + BoundaryDelimiter + Boundary;
BeginContent = System.Text.Encoding.UTF8.GetBytes("\r\n" + BoundaryDelimiter + Boundary + "\r\n");
EndContent = System.Text.Encoding.UTF8.GetBytes("\r\n" + BoundaryDelimiter + Boundary + "--\r\n");
格式化表单数据的方法:
private Byte[] FormDataFormat(String name, String fileName, String contentType)
=> System.Text.Encoding.UTF8.GetBytes(String.Format("Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\nContent-Type:{2}\r\nContent-Transfer-Encoding: binary\r\n\r\n", name, fileName, contentType));
将文件附加到流:
Stream = new MemoryStream();
foreach (var i in files) {
var tempEncode = FormDataFormat("file", i, "application/octet-stream");
var file = System.IO.File.ReadAllBytes(i); // Files are supposed to be small.
Stream.Write(BeginContent, 0, BeginContent.Length);
Stream.Write(tempEncode, 0, tempEncode.Length);
Stream.Write(file, 0, file.Length);
ContentLenght += BeginContent.Length + tempEncode.Length + file.Length;
}
Stream.Write(EndContent, 0, EndContent.Length);
ContentLenght += EndContent.Length;
创建请求:
public HttpWebRequest Request(String method) {
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
request.ContentType = ContentType;
request.KeepAlive = true;
request.Method = method;
request.ContentLength = ContentLenght;
Stream.Seek(0, SeekOrigin.Begin);
Stream.CopyTo(request.GetRequestStream());
Stream.Dispose();
return request;
}
答案 0 :(得分:2)
您没有在问题中显示BoundaryDelimiter
变量声明,但出于此答案的目的,我将假设它的定义如下:
BoundaryDelimiter = "---------------------"
现在您的代码存在的问题是,在计算边界分隔符时,您缺少几个短划线(--
)以符合RFC2388
。
所以而不是:
BeginContent = System.Text.Encoding.UTF8.GetBytes("\r\n" + BoundaryDelimiter + Boundary + "\r\n");
EndContent = System.Text.Encoding.UTF8.GetBytes("\r\n" + BoundaryDelimiter + Boundary + "--\r\n");
你需要这个:
BeginContent = System.Text.Encoding.UTF8.GetBytes("\r\n" + BoundaryDelimiter + "--" + Boundary + "\r\n");
EndContent = System.Text.Encoding.UTF8.GetBytes("\r\n" + BoundaryDelimiter + "--" + Boundary + "--\r\n");
请注意我添加到您的开始和结束内容边界分隔符的其他--
。
检查示例provided here
:
Content-Type: multipart/form-data; boundary=AaB03x
--AaB03x
Content-Disposition: form-data; name="submit-name"
Larry
--AaB03x
Content-Disposition: form-data; name="files"; filename="file1.txt"
Content-Type: text/plain
... contents of file1.txt ...
--AaB03x--
注意边界是如何等于AaB03x
但是分隔符实际上是--AaB03x
,当然结束分隔符是--AaB03x--
。
作为旁注,您可以摆脱ContentLenght
变量(顺便拼写错误:-))并删除此行:
request.ContentLength = ContentLenght
这将简化您的代码,因为HttpWebRequest
类将根据您写入请求流的字节数自动填充Content-Length
标头。
话虽如此,我建议您使用HttpClient
类而不是HttpWebRequest
,因为它已经具有内置功能,可以正确编码这类内容。它肯定会使您的代码更具可读性,因为您不必担心边界,分隔符和内容长度。