微信小程序获取图片使用session(下篇)
概述:
在本人上一篇文章中,微信小程序获取图片使用session(上篇),文章地址:https://blog.csdn.net/shenweihong/article/details/144970945,提出来性能问题,图片比较大的(超过1M)导致小程序setData渲染效率低,本文基于这个问题,描述解决方法。
开发平台:
前端:微信开发者工具,采用原生的js,基础库版本:3.6.5
后台:eclipse,springboot架构,springboot版本:2.6.13
原理:
文章:微信小程序获取图片使用session(上篇),把cookie放在http head中,
1、这里前端我就把cookie直接放在url中,前端只需要处理image属性src的url,不需要手动处理http请求,这个url能不受限制访问后台;
2、后台从请求的url中分离出cookie,和拿到真正想请求的image地址;
3、后台再发起一个http get请求,这个请求带有cookie请求到之前登陆的session中获取。
如下图:
其中两处的后台,是同一个后台程序,只是url不一样
前端代码:
wxml文件
<view class="grid-container">
<view class="grid-item" wx:for="{{itemsShow}}" wx:for-item="item" wx:for-index="index" wx:key="*this">
<image class="image-item" src="{{item.pic}}" bindtap="{{item.act}}"></image>
<text>{{item.tag}}</text>
</view>
</view>
js文件
data: {
itemsShowPreurl: "/Function/WxTopWorkRecord/GetFunctionLogo/",
itemsShow:[],
itemsShowKeep:[],
itemsShowOrg: [
{
tag: "会议",
pic: "metting",
act: "onclickFunMetting"
},
{
tag: "记事",
pic: "record",
act: "onclickFunNoteBook"
},
{
tag: "借录",
pic: "borrow",
act: "onclickFunBorrow"
},
{
tag: "密码",
pic: "password",
act: "onclickFunPassword"
},
{
tag: "系统",
pic: "system",
act: "onclickFunSystem"
},
]
},
setItemsShowData(cl) {
var i = 0;
var tmpStr = null;
if (cl.data.itemsShowKeep == null || cl.data.itemsShowKeep.length <= 0) {
for (i = 0; i < cl.data.itemsShowOrg.length; i++) {
cl.data.itemsShowKeep.push({
tag: "",
pic: "",
act: ""
});
cl.data.itemsShowKeep[i].tag = cl.data.itemsShowOrg[i].tag;
cl.data.itemsShowKeep[i].act = cl.data.itemsShowOrg[i].act;
}
}
for (i = 0; i < cl.data.itemsShowOrg.length; i++) {
tmpStr = app.globalData.baseUrl + "/Guest/WxConvert/" + js_util.util_utf8_str_to_hex(app.globalData.coockieStr, false) + cl.data.itemsShowPreurl + cl.data.itemsShowOrg[i].pic;
cl.data.itemsShowKeep[i].pic = tmpStr;
}
cl.setData({
itemsShow : cl.data.itemsShowKeep
});
},
这里用到了一个临时变量itemsShowKeep,最终的前端刷新显示在变量itemsShow
app.globalData.baseUrl为请求的基础url,这个/Guest/WxConvert/为公共请求的url,辅助字符转十六进制字符函数:js_util.util_utf8_str_to_hex,如下代码
function util_utf8_str_to_hex(charStr, isToArray) {
var i = 0;
var ch = 0;
var result = "";
for (i = 0; i < charStr.length; i++) {
ch = charStr.charCodeAt(i);
if (ch <= 0x7F) {
result += hex_digits.charAt((ch >>> 4) & 0x0f);
result += hex_digits.charAt((ch) & 0x0f);
} else if (ch >= 0x80 && ch <= 0x7FF) {
result += hex_digits.charAt(((0xC0 + (ch >> 6)) >>> 4) & 0x0f);
result += hex_digits.charAt((0xC0 + (ch >> 6)) & 0x0f);
result += hex_digits.charAt(((0x80 + (ch & 0x3F)) >>> 4) & 0x0f);
result += hex_digits.charAt((0x80 + (ch & 0x3F)) & 0x0f);
} else if (ch >= 0x800 && ch <= 0xFFFF) {
result += hex_digits.charAt(((0xE0 + (ch >> 12)) >>> 4) & 0x0f);
result += hex_digits.charAt((0xE0 + (ch >> 12)) & 0x0f);
result += hex_digits.charAt(((0x80 + (0x3F & (ch >> 6))) >>> 4) & 0x0f);
result += hex_digits.charAt((0x80 + (0x3F & (ch >> 6))) & 0x0f);
result += hex_digits.charAt(((0x80 + (ch & 0x3F)) >>> 4) & 0x0f);
result += hex_digits.charAt((0x80 + (ch & 0x3F)) & 0x0f);
}
}
if (isToArray) {
return util_hex_char_to_array(result);
}
return result;
}
function util_hex_char_to_array(hexStrIn) {
var i = 0;
var cnt = 0;
var ele = 0;
var bytesArray = null;
cnt = 0;
for (i = 0; i < hexStrIn.length; i++) {
ele = hexStrIn.charCodeAt(i);
if (ele >= 48 && ele < 48 + 10) {
cnt++;
}
if (ele >= 65 && ele < 65 + 6) {
cnt++;
}
if (ele >= 97 && ele < 97 + 6) {
cnt++;
}
}
bytesArray = new Uint8Array(parseInt((cnt + 1) / 2));
cnt = 0;
for (i = 0; i < hexStrIn.length; i++) {
ele = hexStrIn.charCodeAt(i);
if (ele >= 48 && ele < 48 + 10) {
ele -= 48;
cnt++;
} else if (ele >= 65 && ele < 65 + 6) {
ele = ele - 65 + 10;
cnt++;
} else if (ele >= 97 && ele < 97 + 6) {
ele = ele - 97 + 10;
cnt++;
} else {
continue;
}
if ((cnt % 2) == 1) {
bytesArray[parseInt((cnt - 1) / 2)] = (ele << 4) & 0xF0;
} else {
bytesArray[parseInt((cnt - 1) / 2)] |= ele;
}
}
return bytesArray;
}
后台代码:
公共请求
@Controller
public class ControllerWxConvertSessionGet {
@RequestMapping(value = "/Guest/WxConvert/{cookie}/**", method = RequestMethod.GET)
public void WxConvert(@PathVariable("cookie") String cookieStr, HttpServletRequest request, HttpServletResponse response) {
String getUri = null;
request.getRequestURL();
try {
getUri = getReqProHostPort(request) + DivGetTrueUri(request);
System.out.println("DivGetTrueUri = " + getUri);
System.out.println("cookieStr = " + (new String(DataConvert.stringToHex(cookieStr))));
if (getUri.startsWith("https")) {
HttpClient.HttpsGet(response, new String(DataConvert.stringToHex(cookieStr)), getUri);
} else {
HttpClient.HttpGet(response, new String(DataConvert.stringToHex(cookieStr)), getUri);
}
} catch (MyErrorException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return;
} catch (SocketException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return;
}
}
private String DivGetTrueUri(HttpServletRequest request) throws MyErrorException {
String orgUri = request.getRequestURI();
int i = 0;
int j = 0;
if (orgUri == null) {
throw new MyErrorException("获取原uri为空");
}
if (orgUri.startsWith("/Guest/WxConvert/") == false) {
throw new MyErrorException("原uri前缀不匹配");
}
i = "/Guest/WxConvert/".length();
j = orgUri.indexOf('/', i);
if (j <= 0 || j <= i) {
throw new MyErrorException("没有找到路径");
}
return orgUri.substring(j);
}
public static StringBuffer getReqProHostPort(HttpServletRequest request) {
StringBuffer url = new StringBuffer();
String scheme = request.getScheme();
int port = request.getServerPort();
if (port < 0) {
// Work around java.net.URL bug
port = 80;
}
url.append(scheme);
url.append("://");
url.append(request.getServerName());
if ((scheme.equals("http") && (port != 80))
|| (scheme.equals("https") && (port != 443))) {
url.append(':');
url.append(port);
}
//url.append(request.getRequestURI());
return url;
}
}
http(s)辅助函数
public static void HttpGet(HttpServletResponse response, String cookie, String toUrl) throws SocketException {
String strTmp = null;
byte[] tmpBytes = null;
InputStream inStream = null;
try {
URL url = new URL(toUrl);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
//connection.setRequestProperty("Content-Type", "application/json");
connection.setConnectTimeout(10000);
connection.setReadTimeout(20000);
connection.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.2; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)");
connection.setRequestProperty("Cookie", cookie);
connection.setDoOutput(true);
connection.setDoInput(true);
connection.connect();
//tmpBytes = bodyData;
//connection.getOutputStream().write(tmpBytes);
// strTmp = "";
int responseCode = connection.getResponseCode();
System.out.println("responseCode = " + responseCode);
if (responseCode == 200) {
inStream = connection.getInputStream();
if (response != null) {
response.setStatus(responseCode);
MyStream.readAllToOutStream(inStream, response.getOutputStream());
}
//tmpBytes = MyStream.readAllBytes(inStream);
//strTmp = (new String(tmpBytes));
//System.out.println("post readAllBytes = " + strTmp);
inStream.close();
} else {
strTmp = connection.getResponseMessage();
if (response != null) {
if (strTmp != null && strTmp.length() > 0) {
response.setStatus(responseCode, strTmp);
} else {
response.setStatus(responseCode);
}
}
strTmp = "";
}
connection.disconnect();
} catch (java.net.ConnectException e) {
throw e;
} catch (java.net.SocketException e) {
throw e;
}catch (Exception e) {
e.printStackTrace();
}
//if (strTmp == null) {
// strTmp = "";
//}
//return strTmp;
}
public static void HttpsGet(HttpServletResponse response, String cookie, String toUrl) throws SocketException {
String strTmp = null;
byte[] tmpBytes = null;
InputStream inStream = null;
try {
URL url = new URL(toUrl);
HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
connection.setHostnameVerifier(allHostsValid);
connection.setRequestMethod("GET");
//connection.setRequestProperty("Content-Type", "application/json");
connection.setConnectTimeout(10000);
connection.setReadTimeout(20000);
connection.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.2; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)");
connection.setRequestProperty("Cookie", cookie);
connection.setDoOutput(true);
connection.setDoInput(true);
// connection.setSSLSocketFactory(createSSLSocketFactory());
connection.connect();
//tmpBytes = bodyData;
//connection.getOutputStream().write(tmpBytes);
// strTmp = "";
int responseCode = connection.getResponseCode();
System.out.println("responseCode = " + responseCode);
if (responseCode == 200) {
inStream = connection.getInputStream();
if (response != null) {
response.setStatus(responseCode);
MyStream.readAllToOutStream(inStream, response.getOutputStream());
}
//tmpBytes = MyStream.readAllBytes(inStream);
//strTmp = (new String(tmpBytes));
//System.out.println("post readAllBytes = " + strTmp);
inStream.close();
} else {
strTmp = connection.getResponseMessage();
if (response != null) {
if (strTmp != null && strTmp.length() > 0) {
response.setStatus(responseCode, strTmp);
} else {
response.setStatus(responseCode);
}
}
strTmp = "";
}
connection.disconnect();
} catch (java.net.ConnectException e) {
throw e;
} catch (java.net.SocketException e) {
throw e;
}catch (Exception e) {
e.printStackTrace();
}
//if (strTmp == null) {
// strTmp = "";
//}
//return strTmp;
}
private static HostnameVerifier allHostsValid = new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
};
private static SSLSocketFactory createSSLSocketFactory() {
TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) {
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[] {};
}
} };
// 使用上述TrustManager初始化SSLContext
SSLContext sslContext = null;
try {
sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (KeyManagementException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// 创建一个不进行主机名验证的SSLConnectionSocketFactory
return sslContext.getSocketFactory();
}
最终请求资源的地方
package com.shenweihong.controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import com.shenweihong.html.ResponseFile;
import com.shenweihong.main.UserDir;
@Controller
public class ControllerWxTopWorkRecord {
@GetMapping("/Function/WxTopWorkRecord/GetFunctionLogo/{PicName}")
public void GetFunctionLogo(@PathVariable("PicName") String picName, HttpServletRequest request, HttpServletResponse response) {
System.out.println("picName = " + picName);
response.setContentType("image/jpeg");
ResponseFile.ResponseWriteStreamFile(UserDir.GetResourceDir() + "static/wx_image/public/" + picName + ".jpg", response);
}
}