@Override
public ReturnMsg uploadQRCode(WxQRCodeRes wxQRCodeRes) {
Return msg = new Return();
RmsUserextension rmsUserextension = new RmsUserextension();
if (wxQRCodeRes.getQrcodeBase() == null) { // 图像数据为空
return msg.msg();
}else{
// JDK8以上
Base64.Decoder decoder = Base64.getDecoder();
byte[] bytes = decoder.decode(wxQRCodeRes.getQrcodeBase());//base64解码
for (int i = 0; i < bytes.length; ++i) {
if (bytes[i] < 0) {// 调整异常数据
bytes[i] += 256;
}
}
// 生成jpeg图片
try {
String codeName = "WxQRCode" + wxQRCodeRes.getUserId();
File directory = new File("");// 参数为空
String courseFile = directory.getCanonicalPath();
String codePath = courseFile + "/" + codeName + ".png";
Ulog.info("打印二维码名称"+codeName);
Ulog.info("打印二维码路径"+codePath);
OutputStream out = new FileOutputStream(codePath);
rmsUserextension.setUserId(wxQRCodeRes.getUserId());
rmsUserextension.setUserWxqrcode(codePath);
msg.getDataTable().put("QRCodePath",dao.update(rmsUserextension.where().addEq(RmsUserextension.USER_ID,wxQRCodeRes.getUserId()).model()));
out.write(bytes);
out.flush();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
return msg.msg();
}
}
关键点在于以下几个方面:
1.前端传的图片格式是什么样的?
答:前端可以给我们直接传图片也可以由他们将图片转成base64码传一个字符串给我们,区别在于,第一种方式我们需要自己将图片进行转码,具体的图片转base64码的方法网上有大量教程,并且本身我自己也还没有尝试过,因此这里先跳过。我们着重谈第二种方式,第二种方式是由前端对图片进行转码,将.jpg格式也好.png格式也好转换成带格式前缀的一串base64的码,这个前缀的作用束腰是用来区分图片格式,而这两种图片格式的区别在于当图片背景为透明时,.jpg会以透明状态显示,而.png会显示为白色(也可能是相反?)。但是针对微信二维码来说并不需要考虑背景颜色的问题,因此我们这里可以只选取去掉前缀之后的码值字符串来进行转换存储,当然如果前端传过来的是完整的base64码(包含前缀),我们也可以自己对他进行截取(使用Substring()方法,不详述)。
2.(重要)关于base64码的转换问题?
答:当前端给我们传过来一个base64码之后,我们要对这个码值字符串进行操作,具体如下:
i.如果有前缀,要进行截取,将前缀去掉只对后面的内容进行解析;
ii.对不包含前缀的base64码值进行转换,将其转换成二进制码的数组具体代码如下:
Base64.Decoder decoder = Base64.getDecoder();
byte[] bytes = decoder.decode(wxQRCodeRes.getQrcodeBase());//base64解码
for (int i = 0; i < bytes.length; ++i) {
if (bytes[i] < 0) {// 调整异常数据
bytes[i] += 256;
}
}
其中之所以要调整异常数据,原因如下:
因为byte是有符号的,它表示的范围是-127127,如果要映射到无符号0255,那么0127不用改变,而-128-1对应128~255。
3.图片存储路径的确定问题?
3.1直接确定一个绝对路径
设置一个本地磁盘上的某个位置,从根目录一直到文件名,写死的。
3.2获取项目的相对路径问题(获取项目的根路径)
File directory = new File("");// 参数为空
String courseFile = directory.getCanonicalPath();
String codePath = courseFile + "/" + codeName + ".png";
4.图片的命名问题
注意不要重复,这里用的是用户id进行区分
5.输入输出流的使用问题
//通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的 File 对象 file 指定。
public FileInputStream(File file);
//通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的路径名 name 指定。
public FileInputStream(String name);
```[FileInputStream与FileOutputStream](https://blog.csdn.net/lyb1832567496/article/details/52712218)
[关于File类FileOutPutStream和Byte的转换](https://www.cnblogs.com/DylanZ/p/6269042.html)