zoukankan      html  css  js  c++  java
  • 裸写http body服务报body Unexpected end of multipart data的解决办法

    裸写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之间的字段相隔多少个“ ”,这样就可以了。

  • 相关阅读:
    API网络数据安全
    【值得收藏】一文掌握用户画像系统构建全流程
    手把手教你从0到1学会tensorflow进行模型训练,并能在网页轻松运行
    APP选择第三方消息推送平台时,有哪些需要关注的重要性能指标?
    如何防薅羊毛?个推基于大数据风控引擎助力APP反欺诈!
    微信为什么要搞一个小游戏?
    关于 JS 模块化的最佳实践总结
    张小龙2019微信公开课15个看点总结
    编程:从前有一个傻呆程序员,老婆交给他一项任务,他办了四次才满意
    JS是如何计算 1+1=2 的?
  • 原文地址:https://www.cnblogs.com/zh672903/p/11168559.html
Copyright © 2011-2022 走看看