6.9.3 上传多媒体文件方法封装
通过上面的分析,笔者将上传多媒体文件的操作封装成uploadMedia()方法,该方法的实现如下:
- 1 **
- 2 * 上传媒体文件
- 3 *
- 4 * @param accessToken 接口访问凭证
- 5 * @param type 媒体文件类型(image、voice、video和thumb)
- 6 * @param mediaFileUrl 媒体文件的url
- 7 */
- 8 public static WeixinMedia uploadMedia(String accessToken, String type, String
- mediaFileUrl)
- 9 {
- 10 WeixinMedia weixinMedia = null;
- 11 // 拼装请求地址
- 12 String uploadMediaUrl =
- "http://file.api.weixin.qq.com/cgi-bin/media/upload?access_token=ACCESS_
- TOKEN&type=TYPE";
- 13 uploadMediaUrl = uploadMediaUrl.replace("ACCESS_TOKEN", accessToken).
- replace("TYPE", type);
- 14
- 15 // 定义数据分隔符
- 16 String boundary = "------------7da2e536604c8";
- 17 try {
- 18 URL uploadUrl = new URL(uploadMediaUrl);
- 19 HttpURLConnection uploadConn = (HttpURLConnection) uploadUrl.
- openConnection();
- 20 uploadConn.setDoOutput(true);
- 21 uploadConn.setDoInput(true);
- 22 uploadConn.setRequestMethod("POST");
- 23 // 设置请求头Content-Type
- 24 uploadConn.setRequestProperty("Content-Type", "multipart/form-data;
- boundary=" + boundary);
- 25 // 获取媒体文件上传的输出流(往微信服务器写数据)
- 26 OutputStream outputStream = uploadConn.getOutputStream();
- 27
- 28 URL mediaUrl = new URL(mediaFileUrl);
- 29 HttpURLConnection meidaConn = (HttpURLConnection) mediaUrl.openConnection();
- 30 meidaConn.setDoOutput(true);
- 31 meidaConn.setRequestMethod("GET");
- 32
- 33 // 从请求头中获取内容类型
- 34 String contentType = meidaConn.getHeaderField("Content-Type");
- 35 // 根据内容类型判断文件扩展名
- 36 String fileExt = CommonUtil.getFileExt(contentType);
- 37 // 请求体开始
- 38 outputStream.write(("--" + boundary + "\r\n").getBytes());
- 39 outputStream.write(String.format("Content-Disposition: form-data;
- name=\"media\";filename=\"file1%s\"\r\n", fileExt).getBytes());
- 40 outputStream.write(String.format("Content-Type: %s\r\n\r\n",
- contentType).getBytes());
- 41
- 42 // 获取媒体文件的输入流(读取文件)
- 43 BufferedInputStream bis = new BufferedInputStream(meidaConn.getInputStream());
- 44 byte[] buf = new byte[8096];
- 45 int size = 0;
- 46 while ((size = bis.read(buf)) != -1) {
- 47 // 将媒体文件写到输出流(往微信服务器写数据)
- 48 outputStream.write(buf, 0, size);
- 49 }
- 50 // 请求体结束
- 51 outputStream.write(("\r\n--" + boundary + "--\r\n").getBytes());
- 52 outputStream.close();
- 53 bis.close();
- 54 meidaConn.disconnect();
- 55
- 56 // 获取媒体文件上传的输入流(从微信服务器读数据)
- 57 InputStream inputStream = uploadConn.getInputStream();
- 58 InputStreamReader inputStreamReader = new InputStreamReader(inputStream,
- "utf-8");
- 59 BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
- 60 StringBuffer buffer = new StringBuffer();
- 61 String str = null;
- 62 while ((str = bufferedReader.readLine()) != null) {
- 63 buffer.append(str);
- 64 }
- 65 bufferedReader.close();
- 66 inputStreamReader.close();
- 67 // 释放资源
- 68 inputStream.close();
- 69 inputStream = null;
- 70 uploadConn.disconnect();
- 71
- 72 // 使用JSON-lib解析返回结果
- 73 JSONObject jsonObject = JSONObject.fromObject(buffer.toString());
- 74 System.out.println(jsonObject);
- 75 weixinMedia = new WeixinMedia();
- 76 weixinMedia.setType(jsonObject.getString("type"));
- 77 // type等于thumb时的返回结果和其他类型不一样
- 78 if ("thumb".equals(type))
- 79 weixinMedia.setMediaId(jsonObject.getString("thumb_media_id"));
- 80 else
- 81 weixinMedia.setMediaId(jsonObject.getString("media_id"));
- 82 weixinMedia.setCreatedAt(jsonObject.getInt("created_at"));
- 83 } catch (Exception e) {
- 84 weixinMedia = null;
- 85 log.error("上传媒体文件失败:{}", e);
- 86 }
- 87 return weixinMedia;
- 88 }
第16行代码定义了一个数据分隔符boundary,虽然它的长度没有限制,但也要确保它不会与请求头或请求体中的其他内容重复,最好是随机生成十几位以上的字符串。
第18~24行的作用是与微信服务器建立连接,并设置请求头Content-Type。
第26行的作用是获取媒体文件上传的输出流,准备往微信服务器写数据(请求体)。
第28~31行的作用是与准备上传的媒体文件建立连接,为读取媒体文件做准备。
第34~40行开始构造请求体,并根据媒体文件类型设置请求体中的Content-Disposition和Content-Type,这里调用了CommonUtil类的getFileExt()方法,该方法的定义如下:
- /**
- * 根据内容类型判断文件扩展名
- *
- * @param contentType 内容类型
- * @return
- */
- public static String getFileExt(String contentType) {
- String fileExt = "";
- if ("image/jpeg".equals(contentType))
- fileExt = ".jpg";
- else if ("audio/mpeg".equals(contentType))
- fileExt = ".mp3";
- else if ("audio/amr".equals(contentType))
- fileExt = ".amr";
- else if ("video/mp4".equals(contentType))
- fileExt = ".mp4";
- else if ("video/mpeg4".equals(contentType))
- fileExt = ".mp4";
- return fileExt;
- }
uploadMedia()方法的第43~49行是往请求体中追加媒体文件的内容。
第51行是往请求体中追加结束符。
第57~70行的作用是读取上传文件后微信服务器返回的内容。
第73~82行使用JSON-lib解析返回的JSON数据,需要注意的是,如果上传的媒体文件类型为thumb,上传成功后返回的结果与其他3种类型(图片、语音和视频)的不一样,前者返回的媒体文件标识是thumb_media_id,后者返回的文件标识是media_id。最后,将所有返回参数封装在WeixinMedia中,该类的代码如下:
- package org.liufeng.course.pojo;
- /**
- * 媒体文件信息
- *
- * @author liufeng
- * @date 2013-11-09
- */
- public class WeixinMedia {
- // 媒体文件类型
- private String type;
- // 媒体文件标识或缩略图的媒体文件标识
- private String mediaId;
- // 媒体文件上传的时间
- private int createdAt;
- public String getType() {
- return type;
- }
- public void setType(String type) {
- this.type = type;
- }
- public String getMediaId() {
- return mediaId;
- }
- public void setMediaId(String mediaId) {
- this.mediaId = mediaId;
- }
- public int getCreatedAt() {
- return createdAt;
- }
- public void setCreatedAt(int createdAt) {
- this.createdAt = createdAt;
- }
- }