#2
sam_jiang2025-01-05 16:43
网上的代码做参考,我参考了他的代码
程序代码: /** * 上传图文消息内的图片获取URL * http请求方式: POST,https协议 以表单形式提交 * https://api.weixin.*/ @Test public void test6(){ String redisToken = wxService.getRedisToken(); String urlStr = "https://api.weixin./cgi-bin/media/uploadimg?access_token=ACCESS_TOKEN"; String replaceUrl = urlStr.replace("ACCESS_TOKEN", redisToken); File file = new File("/Users/LiuShihao/IdeaProjects/wxthepublic/FtA17e_zIAqlFyfOZ-tpkbhPmZFQ-EIKGef4NwwPfNaPqGARTs4eX7yrX8gAV5Mv.jpg"); StringBuilder resp = new StringBuilder(); String result=null; try { URL urlObj = new URL(replaceUrl); HttpsURLConnection conn = (HttpsURLConnection) urlObj.openConnection(); conn.setRequestMethod("POST");//以POST方式提交表单 conn.setDoOutput(true); conn.setDoInput(true); conn.setUseCaches(false); conn.setRequestProperty("Connection","Keep-Alive"); conn.setRequestProperty("Charset","UTF-8"); //数据边界 String boundary = "----------"+System.currentTimeMillis(); conn.setRequestProperty("Content-Type","multipart/form-data; boundary="+boundary); //获取输出流 OutputStream out = conn.getOutputStream(); //创建文件输入流 FileInputStream fis = new FileInputStream(file); StringBuilder sb = new StringBuilder(); sb.append("--"); sb.append(boundary); sb.append("\r\n"); sb.append("Content-Disposition: form-data;name=\"media\"; filename=\""+file.getName()+"\"\r\n"); sb.append("Content-Type: applicatin/octet-stream\r\n\r\n"); out.write(sb.toString().getBytes()); byte[] bytes = new byte[1024]; int len; while((len = fis.read(bytes)) != -1){ out.write(bytes,0,len); } String foot = "\r\n--"+boundary+"--\r\n"; out.write(foot.getBytes()); out.flush(); out.close(); //读取数据 if(HttpsURLConnection.HTTP_OK==conn.getResponseCode()){ StringBuffer strbuffer=null; BufferedReader reader=null; try { strbuffer=new StringBuffer(); reader=new BufferedReader(new InputStreamReader(conn.getInputStream())); String lineString=null; while((lineString=reader.readLine())!=null){ strbuffer.append(lineString); } result=strbuffer.toString(); } catch (IOException e) { System.out.println("发送POST请求出现异常!"+e); e.printStackTrace(); }finally{ if(reader!=null){ reader.close(); } } } } catch (Exception e) { e.printStackTrace(); } System.out.println(result); //resp:{"url":"http:\/\/mmbiz.\/mmbiz_jpg\/OsaJQib8ibD8ActRfkHSkvZsntjEjmicVGibcWic0Kbkq8pgnf4BJgytEOUBxmlIM1IBCPsWLOXUW0dUwAZziaiajwNfw\/0"} //http://mmbiz./mmbiz_jpg/OsaJQib8ibD8ActRfkHSkvZsntjEjmicVGibcWic0Kbkq8pgnf4BJgytEOUBxmlIM1IBCPsWLOXUW0dUwAZziaiajwNfw/0 } |
最近在整合微信的一个素材库的vfp访问类,以便做到素材的获取,上传和下载,准备分享给各位狐友。
可惜现在遇到一个瓶颈,微信API接口要求以form-data的格式向api接口post数据,网上搜索了很多文章都是其他有语言的,不是很看得懂,不知其所以然。
论坛里有没有对此理解比较深刻的狐友?可以帮我解释一下form-data的格式?
下面是我网上搜到的对multipart/form-data请求体的布局说明:
# 请求头 - 这个是必须的,需要指定Content-Type为multipart/form-data,指定唯一边界值
Content-Type: multipart/form-data; boundary=${Boundary}
# 请求体
--${Boundary}
Content-Disposition: form-data; name="name of file"
Content-Type: application/octet-stream
bytes of file
--${Boundary}
Content-Disposition: form-data; name="name of pdf"; filename="pdf-file.pdf"
Content-Type: application/octet-stream
bytes of pdf file
--${Boundary}
Content-Disposition: form-data; name="key"
Content-Type: text/plain;charset=UTF-8
text encoded in UTF-8
--${Boundary}--
媒体类型multipart/form-data相对于其他媒体类型如application/x-www-form-urlencoded等来说,最明显的不同点是:
请求头的Content-Type属性除了指定为multipart/form-data,还需要定义boundary参数
请求体中的请求行数据是由多部分组成,boundary参数的值模式--${Boundary}用于分隔每个独立的分部
每个部分必须存在请求头Content-Disposition: form-data; name="${PART_NAME}";,这里的${PART_NAME}需要进行URL编码,另外filename字段可以使用,用于表示文件的名称,但是其约束性比name属性低(因为并不确认本地文件是否可用或者是否有异议)
每个部分可以单独定义Content-Type和该部分的数据体
请求体以boundary参数的值模式--${Boundary}--作为结束标志
每个--${Boundary}之前默认强制必须为CRLF,如果某一个部分的文本类型请求体以CRLF结尾,那么在请求体的二级制格式上,必须显式存在两个CRLF,如果某一个部分的请求体不以CRLF结尾,可以只存在一个CRLF,这两种情况分别称为分隔符的显式类型和隐式类型,说的比较抽象。
*****这里的CRLF,对应与VFP是不是CHR(10)+CHR(13)??? 我就是这样理解的,应该不是chr(13)吧?
微信api接口说明如下:
上传图文消息内的图片获取URL
本接口所上传的图片不占用公众号的素材库中图片数量的100000个的限制。图片仅支持jpg/png格式,大小必须在1MB以下。
接口调用请求说明
http请求方式: POST,https协议 https://api.weixin. 调用示例(使用curl命令,用FORM表单方式上传一个图片): curl -F media=@test.jpg "https://api.weixin.
参数说明
参数 是否必须 说明
access_token 是 调用接口凭证
media 是 form-data中媒体文件标识,有filename、filelength、content-type等信息
*****这里的参数media,它的值是不是就是上面的请求体?
请求体显然不是通过url传递的,应该不是在网址后加?access_token=ACCESS_TOKEN&media=***请求体***来传递的
而是以xmlhttp.send("***请求体***")来传递的,对吧?那上面那个media参数应该如何传递呢?
我的请求体是这样的:
content-type: multipart/form-data; boundary=designed by Sam Jiang(这里有一个chr(10)+chr(13))
--designed by Sam Jiang(这里有一个chr(10)+chr(13))
Content-Disposition: form-data;name="media";filename="/A.JPG";filelength=19930(这里有一个chr(10)+chr(13))
Content-Type: image/jpeg(这里有一个chr(10)+chr(13))&&Content-Type: applicatin/octet-stream 换这个也不行。
<这里是图片的二进制字符串>(这里有一个chr(10)+chr(13))
--designed by Sam Jiang--(这里有一个chr(10)+chr(13))
微信api接口返回的的错误是:
{"errcode":41005,"errmsg":"media data missing hint: [GdNTya0295w487] rid: 677a44f7-6fdd831b-3d684604"}
调试了很久,不知道到底错在哪里。。。
好累