微信JS-SDK实现上传图片功能
最近在项目开发中,有一个在微信WEB项目中上传图片的需求,一开始使用了传统的<input type="file">的方式去实现,但是后面发现在使用这种传统模式时会由于手机系统的差异而导致一系列的问题,后改用微信JSSDK的方式来实现,做的过程中也遇到了一些小坑,把经验贴出来给大家分享一下,让大家少走点弯路。
总的来说,利用JSSDK来实现该功能一共分为四步。
1. 调用wx.config(),初始化jssdk的配置,并在jsApiList中配置上传图片需要的四个api('chooseImage','previewImage','uploadImage','downloadImage')
wx.config({
debug : false,
appId : data.appId,
timestamp : data.timestamp,
nonceStr : data.nonceStr,
signature : data.signature,
jsApiList : [
'chooseImage',
'previewImage',
'uploadImage',
'downloadImage'
]
});
2.点击图片时,调用wx.chooseImage(),让用户去选择图片或拍照
function wxChooseImage() {
wx.chooseImage({
count: 1,
sizeType: ['original', 'compressed'],
sourceType: ['album', 'camera'],
success: function (data) {
var localIds = data.localIds[0].toString();
wxuploadImage(localIds);
}
});
}
3.选择完图片后调用wx.chooseImage(),将图片上传到微信服务器
function wxuploadImage(e) {
layer.load(1);
wx.uploadImage({
localId: e,
isShowProgressTips: 0,
success: function (res) {
fileUpload(res.serverId);
}
});
}
4.利用mediaId将图片从微信服务器下载到本地或项目的图片服务器路径下,并展示图片
function fileUpload(mediaId) {
$.ajax({
url: KY.basePath + "/image/upload.htm",
dataType: 'json',
data: {
"mi": mediaId
},
type: "post",
success: function(result) {
$("#imghead").attr("src", KY.imageServer + result.path);
}
});
}
附:服务端从微信服务器下载图片的代码,在此处,我是将图片从微信服务器下载后调用另一个专门负责上传图片的项目去进行的上传操作,大家也可以在第73行代码获取到流之后下载到本地。
package com.hyde.carelink2.wechat.utils; import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map; import org.apache.commons.httpclient.NameValuePair;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.content.ByteArrayBody;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import com.fasterxml.jackson.databind.ObjectMapper;
import com.hyde.carelink2.wechat.domain.upload.UploadImagResponse;
import com.hyde.carelink2.wechat.service.wechat.WechatServerCenter;
import com.hyde.common.StatusCode;
import com.hyde.common.enums.ImageToken;
import com.hyde.common.enums.ProjectType;
import com.hyde.common.utils.HttpUtil;
import com.hyde.config.enums.ConfigType;
import com.hyde.config.impl.CommonConfig; /**
* @author WangHuijie
*/
public class DownloadImageUtil { private final static Logger LOGGER = LoggerFactory.getLogger(DownloadImageUtil.class); private static ObjectMapper objectMapper = new ObjectMapper(); /**
* 从微信服务器获取媒体文件
*
* @param param
* @param mediaId
* @param request
* @return
*/
public static Map<String, String> getImageFromWechat(String mediaId) { Map<String, String> map = new HashMap<String, String>();
String accessToken = ""; // 接口访问凭证
try {
accessToken = WechatServerCenter.getAccessToken();
} catch (Exception e) {
LOGGER.error(e.getMessage(), e);
}
String filePath = "";
// 拼接请求地址
String requestUrl = "http://file.api.weixin.qq.com/cgi-bin/media/get?access_token=" + accessToken + "&media_id=" + mediaId;
try {
URL url = new URL(requestUrl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setDoInput(true);
conn.setDoOutput(true);
conn.setRequestMethod("GET");
conn.setRequestProperty("Content-Type", "application/form-data");
InputStream inputStream = conn.getInputStream(); if (inputStream != null) {
HttpURLConnection conn1 = (HttpURLConnection) url.openConnection();
conn1.setDoInput(true);
conn1.setDoOutput(true);
conn1.setRequestMethod("GET");
conn1.setRequestProperty("Content-Type", "application/form-data");
InputStream inputStream1 = conn1.getInputStream(); if (inputStream1 != null) {
// 根据内容类型获取扩展名
String contentType = conn1.getHeaderField("Content-Type");
String expandName = getFileexpandedName(contentType);
String fileName = mediaId + expandName;
filePath = getUploadServerPath(inputStream1, contentType, fileName);
map.put("path", filePath);
map.put("code", String.valueOf(StatusCode.SUCCESS.getIndex()));
map.put("msg", StatusCode.SUCCESS.getMessage());
} else {
map.put("code", String.valueOf(StatusCode.ERROR.getIndex()));
map.put("msg", StatusCode.ERROR.getMessage());
}
} else {
map.put("code", String.valueOf(StatusCode.ERROR.getIndex()));
map.put("msg", StatusCode.ERROR.getMessage());
}
inputStream.close();
conn.disconnect();
} catch (Exception e) {
LOGGER.error(e.getMessage(), e);
}
return map;
} public static String getUploadServerPath(InputStream inputStream, String contentType, String fileName) { String filePath = null;
byte[] bytes = new byte[0];
try {
bytes = toByteArray(inputStream);
} catch (IOException e) {
LOGGER.error(e.getMessage(), e);
}
String token = "DM5344d93e19c41adb5e0f5531bdd0336";
ProjectType projectType = ProjectType.CARELINK2;
ImageToken type = ImageToken.CARELINK2_USER_PORTRAIT;
UploadImagResponse response = uploadImage(bytes, token, contentType, fileName, projectType, type);
if (response != null) {
filePath = response.getFilePath();
}
return filePath;
} /**
* 执行文件上传到图片服务器
*
* @param bytes
* @param token
* @param contentType
* @param fileName
* @param param
* @return
*/
protected static UploadImagResponse uploadImage(byte[] bytes, String token, String contentType, String fileName, ProjectType projectType, ImageToken type) { try {
ByteArrayBody arrayBody = new ByteArrayBody(bytes, ContentType.create(contentType), fileName);
List<NameValuePair> pairs = new ArrayList<NameValuePair>();
NameValuePair projectTypePair = new NameValuePair("p", String.valueOf(projectType.getIndex()));
pairs.add(projectTypePair);
NameValuePair typePair = new NameValuePair("type", String.valueOf(type.getIndex()));
pairs.add(typePair);
String url = CommonConfig.getConfig(ConfigType.UPLOAD_SERVICE_URL, String.class);
String status = HttpUtil.postFile(url, arrayBody, token, pairs);
UploadImagResponse response = objectMapper.readValue(status, UploadImagResponse.class);
return response;
} catch (Exception e) {
LOGGER.error(e.getMessage(), e);
}
return null;
} /**
* 将输入流转为byte数组
* @param input
* @return
* @throws IOException
*/
public static byte[] toByteArray(InputStream input) throws IOException {
ByteArrayOutputStream output = new ByteArrayOutputStream();
byte[] buffer = new byte[4096];
int n = 0;
while (-1 != (n = input.read(buffer))) {
output.write(buffer, 0, n);
}
return output.toByteArray();
} /**
* 根据内容类型判断文件扩展名
* @param contentType 内容类型
* @return
*/
public static String getFileexpandedName(String contentType) { String fileEndWitsh = "";
if ("image/jpeg".equals(contentType)) {
fileEndWitsh = ".jpg";
} else if ("audio/mpeg".equals(contentType)) {
fileEndWitsh = ".mp3";
} else if ("audio/amr".equals(contentType)) {
fileEndWitsh = ".amr";
} else if ("video/mp4".equals(contentType)) {
fileEndWitsh = ".mp4";
} else if ("video/mpeg4".equals(contentType)) {
fileEndWitsh = ".mp4";
}
return fileEndWitsh;
} }
微信JS-SDK实现上传图片功能的更多相关文章
- 实战微信JS SDK开发:贺卡制作与播放(1)
前段时间忙于CanTK 2.0的开发,所以博客一直没有更新.CanTK 2.0主要增强了游戏和富媒体的开发,现在编码和测试基本完成了,等文档完成了再正式发布,里面有不少激动人心的功能,等发布时再一一细 ...
- 微信JS SDK接入的几点注意事项
微信JS SDK接入,主要可以先参考官网说明文档,总结起来有几个步骤: 1.绑定域名:先登录微信公众平台进入“公众号设置”的“功能设置”里填写“JS接口安全域名”.备注:登录后可在“开发者中心”查看对 ...
- 微信js sdk上传多张图片
微信js sdk上传多张图片,微信上传多张图片 该案例已tp3.2商城为例 直接上代码: php代码: public function ind(){ $appid="111111111111 ...
- 微信js SDK接口
微信JS-SDK说明文档 http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html 一.微信登录功能 在进行微信OAut ...
- 微信JS SDK配置授权,实现分享接口
微信开放的JS-SDK面向网页开发者提供了基于微信内的网页开发工具包,最直接的好处就是我们可以使用微信分享.扫一扫.卡券.支付等微信特有的能力.7月份的时候,因为这个分享的证书获取问题深深的栽了一坑, ...
- 微信开发(2):微信js sdk分享朋友圈,朋友,获取config接口注入权限验证(转)
进行微信开发已经一阵子了,从最初的什么也不懂,到微信授权登录,分享,更改底部菜单,素材管理,等. 今天记录一下微信jssdk 的分享给朋友的功能,获取config接口注入. 官方文档走一下简单说:四步 ...
- 调用微信js sdk
场景:需要调用微信获取当前位置的借口. 途径:查看微信 https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141115 .后 ...
- 微信JS SDK使用权限签名算法
jsapi_ticket 生成签名之前必须先了解一下jsapi_ticket,jsapi_ticket是公众号用于调用微信JS接口的临时票据.正常情况下,jsapi_ticket的有效期为7200秒, ...
- 微信js sdk分享开发摘记java版
绑定域名和引入js的就不说了 废话不说直接上代码 public void share(HttpServletRequest request) throws Exception { StringBuff ...
- 微信JS SDK Demo 官方案例[转]
摘要: 微信JS-SDK是微信公众平台面向网页开发者提供的基于微信内的网页开发工具包. 通过使用微信JS-SDK,网页开发者可借助微信高效地使用拍照.选图.语音.位置等手机系统的能力,同时可以直接使用 ...
随机推荐
- 【转】[置顶] 在Android中显示GIF动画
gif图动画在Android中还是比较常用的,比如像新浪微博中,有很多gif图片,而且展示非常好,所以我也想弄一个.经过我多方的搜索资料和整理,终于弄出来了,其实github上有很多开源的gif的展示 ...
- IOPS、带宽(band width)、吞吐量 (throughput)
SAN和NAS存储一般都具备2个评价指标:IOPS和带宽(throughput),两个指标互相独立又相互关联.体现存储系统性能的最主要指标是IOPS. IOPS (Input/Output Per ...
- Xcode下载模拟器太慢?
在Xcode里下载模拟器,速度实在是太慢了.点击下载,卡住十几分钟才开始下载,并且龟速进行. 解决方案:获取模拟器下载地址,自己选择下载器进行下载. 找到下载链接 打开 Console.app(苹果电 ...
- C++ 函数的二义性
函数二义性是一种编译时发生的错误,造成二义性调用的原因 是在函数匹配时两个或多个函数提供的匹配一样好,编译时找 不到唯一的最佳匹配. 列: #include <iostream> usin ...
- Mysql5.7登录错误1045和1130的解决方法,亲测有用,希望能帮助到你们。
Mysql (针对Mysql5.7版本,其他版本可能略有不同) 错误:1045 解决方法: 以管理员身份运行cmd(win8系统:win+x 键 ,再按 A键 ),进入Mysql安装目录下的bin目录 ...
- 关于 class helper for ... 语法
转载于万一的博客https://www.cnblogs.com/del/archive/2009/10/13/1582789.html class helper 可能是从 Delphi 2007 增加 ...
- 数据库之mongodb
启动mongodb服务端 : sudo service mongod start 或者 sudo /usr/local/mongodb/bin/mongod --config /etc/mongodb ...
- WPF不同线程之间的控件的访问
原文:WPF不同线程之间的控件的访问 WPF不同线程之间的控件是不同访问的,为了能够访问其他线程之间的控件,需要用Dispatcher.Invoke执行一个新的活动即可. 例如: public voi ...
- 洛谷 P4018 Roy&October之取石子
洛谷 P4018 Roy&October之取石子 题目背景 Roy和October两人在玩一个取石子的游戏. 题目描述 游戏规则是这样的:共有n个石子,两人每次都只能取 p^kpk 个(p为质 ...
- [NOI2016]区间 线段树
[NOI2016]区间 LG传送门 考虑到这题的代价是最长边减最短边,可以先把边按长度排个序,双指针维护一个尺取的过程,如果存在包含某个点的区间数\(\ge m\),就更新答案并把左指针右移,这样做的 ...