部分手机在图片上传的时候,调取不到sd卡相册或其余图片,为了解决这个兼容性问题,同一个页面使用了两种图片上传方案。javascript
html5 :图片编码成base64 ,发送到后台,解码存储。这种方法用于解决非微信浏览器的上传问题。html
jsapi:用于解决微信浏览器的上传问题。前端
思路:html5
首先判断是不是微信浏览器(微信js接口提供方法),而后调用上面不一样的方法。java
这里记下jfinal整合jsapi的关键代码和流程 。json
前端页面须要一段javascript ,官方文档有详细说明,如下个人configapi
wx.config({ debug: true, appId: 'wx23eeb004xxxx8ecb', // 必填,公众号的惟一标识 timestamp:'${timestamp}', // 必填,生成签名的时间戳 nonceStr: 't8bI2mW5Mxxxx20Y', // 必填,生成签名的随机串 signature: '${signature}', jsApiList: [ 'chooseImage' ] });
如下是前端页面对应的ctrl ,惯例只是关键部分浏览器
//微信 ApiConfig ac = new ApiConfig(); String token = ConfigUtil.get("weixinToken"); String appid = ConfigUtil.get("weixinAppId"); String secret = ConfigUtil.get("weixinSecret"); // 配置微信 API 相关常量 ac.setToken(token); ac.setAppId(appid); ac.setAppSecret(secret); /** * 是否对消息进行加密,对应于微信平台的消息加解密方式: * 1:true进行加密且必须配置 encodingAesKey * 2:false采用明文模式,同时也支持混合模式 */ ac.setEncryptMessage(false); ac.setEncodingAesKey(ConfigUtil.get("weixinEncodingAESKey")); ApiConfigKit.setThreadLocalApiConfig(ac); //必须 JssdkTicket jssdkTicket = JssdkTicketUtil.getJssdkTicket(); if (!jssdkTicket.getErrmsg().equals("ok")){ setAttr("errormsg","如需使用图片上传功能,请刷新页面重试"); }else { String fuckU= DateUtil.getCurMis().toString().substring(0,10); String tempStr = new StringBuilder().append("jsapi_ticket=" + jssdkTicket.getTicket() + "&noncestr=t8bI2mW5Mma0I20Y×tamp=" + fuckU + "&url=" + getRequest().getRequestURL()+"").toString(); System.out.println("string1="+tempStr); tempStr = EncryptionKit.sha1Encrypt(tempStr); System.out.println("加密后="+tempStr); setAttr("timestamp", fuckU); setAttr("signature",tempStr); } createToken("blogToken", 30 * 60); render(AppConst.PATH_WAP_PC+"/abc.ftl");
如下是JssdkTicketUtil ,该util用于缓存jsapi_ticket,也是微信官方文档中一再强调的东西缓存
public class JssdkTicketUtil { private static JssdkTicket jssdkTicket; public static JssdkTicket getJssdkTicket() { if(jssdkTicket != null && jssdkTicket.isAvailable()) { return jssdkTicket; } else { refreshAccessToken(); return jssdkTicket; } } private static void refreshAccessToken() { jssdkTicket = requestJssdkTicket(); } private static synchronized JssdkTicket requestJssdkTicket() { JssdkTicket result = null; AccessToken accessToken = AccessTokenApi.getAccessToken(); String json = HttpKit.get("https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=" + accessToken.getAccessToken() + "&type=jsapi"); result = new JssdkTicket(json); if(!result.isAvailable()) { refreshAccessToken(); } return result; } }
如下是jssdkTicket ,用于存储信息服务器
public class JssdkTicket { private String jsapi ;//服务器返回 private Long expiredTime ; //过时时间 private Integer errcode; //错误码 private String errmsg; //错误信息 private String ticket; //票据 private Integer expires_in; // public JssdkTicket(String jsapiStr){ this.jsapi = jsapiStr; try { Map e = (Map)(new ObjectMapper()).readValue(jsapiStr, Map.class); this.expires_in = (Integer)e.get("expires_in"); this.errcode = (Integer)e.get("errcode"); this.errmsg = (String)e.get("errmsg"); this.ticket = (String)e.get("ticket"); if(this.expires_in != null) { this.expiredTime = Long.valueOf(System.currentTimeMillis() + (long)((this.expires_in.intValue() - 5) * 1000)); } } catch (Exception var3) { throw new RuntimeException(var3); } } public boolean isAvailable() { return this.expiredTime == null ? false : (this.errcode != 0 ? false : (this.expiredTime.longValue() < System.currentTimeMillis() ? false : this.ticket != null)); } public String getJsapi() { return jsapi; } public Long getExpiredTime() { return expiredTime; } public Integer getErrcode() { return errcode; } public String getErrmsg() { return errmsg; } public String getTicket() { return ticket; } public Integer getExpires_in() { return expires_in; } }
以上两个类完成参照jfinal-weixin-1.2中对access_token的处理方式 。感谢jfinal做者 @jfinal
:::::::::::::::::::::::::::::::::::::::::::::::::::
2015-05-29 16:29:58 更新
图片上传完成后,须要从微信服务器下载图片并保存到本地服务器
savePath = HttpClientKit.getFileAndSave("http://file.api.weixin.qq.com/cgi-bin/media/get?access_token=" + ss.getAccessToken() + "&media_id=" + list.get(i));
PS:savePath是本地服务器的保存路径
getFileAndSave方法的关键代码以下(须要引入commons-httpclient.jar):
/** * 从微信服务器取图片并保存到服务器指定路径 * @param url 微信服务器路径 * @return 本地服务器路径 */ public static String getFileAndSave(String url) { String result = ""; SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd"); String ymd = sdf.format(new Date()); String savePath = PathKit.getWebRootPath() + "/photo/"+ymd+"/"; File uploadDir = new File(savePath); if (!uploadDir.exists()) { uploadDir.mkdirs(); } if (!uploadDir.isDirectory()) { return "1"; //上传目录不存在。 } if (!uploadDir.canWrite()) { return "2"; //上传目录没有写权限 } SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmss"); // 时间戳 String newFileName = df.format(new Date()) + "_" + new Random().nextInt(1000) + ".jpg"; // 拼文件名 savePath += newFileName; result = "/photo/"+ymd+"/" + newFileName; HttpClient client = new HttpClient(); GetMethod get = new GetMethod(url); // String filePath = FileKit.getSaveRealPath("jpg"); try { File storeFile = new File(savePath); FileOutputStream output = null; client.executeMethod(get); output = new FileOutputStream(storeFile); output.write(get.getResponseBody()); output.close(); } catch (HttpException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return result; }