部分手機在圖片上傳的時候,調取不到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; }