裸写http body服务报body Unexpected end of multipart data的解决办法
抛出异常:
- 案例 调用腾讯OCR营业执照识别报错。
调用腾讯OCR识别时签名没有问题,图片base64也没有问题,但是确收到对方服务报“内部错误”,经过联系沟通,内部错误报:
“caught error Error: Unexpected end of multipart data”
抓包
通过抓包如下:
POST https://recognition.image.myqcloud.com/ocr/bizlicense HTTP/1.1
Content-Type: multipart/form-data; boundary=----------8d7055498b35e31
Authorization: yzo1HrKzdUF2rmYpiRoF482vvglhPTEyNTE3OTMwODAmYj10ZW5jZW50eXVuJms9QUtJRGExRDhtQmdBbEVWWWFSemp6emg5S0l6UWl2eTJDZUJUJmU9MTU2NTMzOTcxOSZ0PTE1NjI3NDc3MTkmcj0xOTA3MTAxNjM1JnU9MCZmPQ==
Host: recognition.image.myqcloud.com
Content-Length: 249
Expect: 100-continue
------------8d7055498b35e31
Content-Disposition: form-data; name="appid";
1251793080
------------8d7055498b35e31
Content-Disposition: form-data; name="image"; filename="yyzz.jpg"
Content-Type: image/jpeg
----------8d7055498b35e31--
解决问题
乍看上面抓包好像没有什么问题,难道是Authorization加密出错?图片base64出错?
其实真正出错的的原因是Content-Type里面的横线要比body里面的少两个。body的最后一定要有两个横线结尾,并且body的横线多少要一致(这个也是最重要的,不是有横线就可以了)。
- 能正确运行的包应该如下:
POST https://recognition.image.myqcloud.com/ocr/bizlicense HTTP/1.1
Content-Type: multipart/form-data; boundary=----------8d7055498b35e31
Authorization: yzo1HrKzdUF2rmYpiRoF482vvglhPTEyNTE3OTMwODAmYj10ZW5jZW50eXVuJms9QUtJRGExRDhtQmdBbEVWWWFSemp6emg5S0l6UWl2eTJDZUJUJmU9MTU2NTMzOTcxOSZ0PTE1NjI3NDc3MTkmcj0xOTA3MTAxNjM1JnU9MCZmPQ==
Host: recognition.image.myqcloud.com
Content-Length: 249
Expect: 100-continue
------------8d7055498b35e31
Content-Disposition: form-data; name="appid";
1251793080
------------8d7055498b35e31
Content-Disposition: form-data; name="image"; filename="yyzz.jpg"
Content-Type: image/jpeg
------------8d7055498b35e31--
附C#调用腾讯OCR营业执照识别的部分源码
static void IdentityBusinessLicense(string url)
{
HttpWebRequest webReq = (HttpWebRequest)WebRequest.Create(new Uri(url));
Stream memStream = new MemoryStream();
webReq.Method = "POST";
string boundary = "----------" + DateTime.Now.Ticks.ToString("x");// 边界符
webReq.ContentType = "multipart/form-data; boundary=" + boundary;
//webReq.ContentType = "multipart/form-data;";
byte[] enter = Encoding.ASCII.GetBytes("
"); //换行
memStream.Write(enter, 0, enter.Length);
Dictionary<string, string> dic = new Dictionary<string, string>()
{
{"appid",OCRConfig.appid}
};
//写入文本字段
string inputPartHeaderFormat = "--" + boundary + "
" + "Content-Disposition: form-data; name="{0}";" + "
{1}
";
foreach (var kv in dic)
{
string inputPartHeader = string.Format(inputPartHeaderFormat, kv.Key, kv.Value);
var inputPartHeaderBytes = Encoding.ASCII.GetBytes(inputPartHeader);
memStream.Write(inputPartHeaderBytes, 0, inputPartHeaderBytes.Length);
}
var fileStream = new FileStream("yyzz.jpg", FileMode.Open, FileAccess.Read);
// 写入文件
string imagePartHeader = "--" + boundary + "
" +
"Content-Disposition: form-data; name="{0}"; filename="{1}"
" +
"Content-Type: image/jpeg
";
var header = string.Format(imagePartHeader, "image", "yyzz.jpg");
var headerbytes = Encoding.UTF8.GetBytes(header);
memStream.Write(headerbytes, 0, headerbytes.Length);
var buffer = new byte[1024];
int bytesRead;
while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
{
memStream.Write(buffer, 0, bytesRead);
}
// 最后的结束符
byte[] endBoundary = Encoding.ASCII.GetBytes("
--" + boundary + "--
");
memStream.Write(endBoundary, 0, endBoundary.Length);
// webReq.ContentLength = memStream.Length;
webReq.Headers.Add(HttpRequestHeader.Authorization, OCRApi.HmacSha1Sign());
webReq.Host = OCRConfig.Host;
var requestStream = webReq.GetRequestStream();
memStream.Position = 0;
memStream.CopyTo(requestStream);
HttpWebResponse response = (HttpWebResponse)webReq.GetResponse();
StreamReader sr = new StreamReader(response.GetResponseStream(), Encoding.UTF8);
var ret = sr.ReadToEnd();
sr.Close();
response.Close();
requestStream.Close();
memStream.Close();
}
总结
1、Content-Type: multipart/form-data; boundary=----------8d7055498b35e31 这里header的boundary横线要比body的少两个
2、------------8d7055498b35e31 body里面的横线要比header的横线要多两个且所有body的横线长度要一致,不是有横线就可以了。
3、特别注意结尾处应该还有两个“--”,注意是两个横线
4、还有一点就是要注意header之间,header与body之间,body与body之间的字段相隔多少个“ ”,这样就可以了。