有没有jfinal批量生成二维码,并打包下载的例子。

最近要做个二维码管理平台,主要是为某一个企业生成二维码,数量在每次十万个左右。大佬们!帮帮忙啊。

评论区

CrazyZH

2019-03-12 18:49

之前做了一版,但是生成,大致思路是在项目目录下生成了一个专门存放二维码的文件夹。然后生成二维码放在该文件夹里。再打包成zip文件下载,关闭输出流的时候删除之前生成的所有文件。但是方法执行的太慢了。感觉时间花在了生成文件和删除文件上了。有什么方法优化么?

JFinal

2019-03-12 20:12

每次生成的数量很多,可以用多线程并发去生成

生成二维码的代码,拿到 jfinal 的 com.jfinal.render.QrRender.java 源码,将里头的输出 OutputStream 定向到你自己的 FileOutputStream 即可

先搞定生成,然后用 java 自带的 visual vm 工具检查哪里是瓶颈,有针对性的优化性能即可

CrazyZH

2019-03-13 12:05

@JFinal 这个地方能不能不在服务器生成文件,然后执行下载呢,因为生成完成之后这些文件就没用了,后续的访问都是给页面code,页面自己根据code生成的二维码。

JFinal

2019-03-13 14:13

@CrazyZH 这个随便玩,B/S 架构在服务端生成为好。 C/S 架构可以考虑在客户端生成

CrazyZH

2019-03-14 09:51

@JFinal
昨天又修改了下,生成二维码的方法:

public class MyQrcodeRender extends Render{

private String content;
private int width;
private int height;
private ErrorCorrectionLevel errorCorrectionLevel;
private String savePath; // 保存到那个地址
private String urlStr; // 拼接在content前面的地址如http://....
/**
* 构造方法,经测试不指定纠错参数时,默认使用的是 'L' 最低级别纠错参数
* @param content 二维码携带内容
* @param width 二维码宽度
* @param height 二维码高度
*/
public MyQrcodeRender(String content, int width, int height, String savePath,String urlStr) {
init(content, width, height, null, savePath, urlStr);
}

private void init(String content, int width, int height, ErrorCorrectionLevel errorCorrectionLevel, String savePath, String urlStr) {
if (StrKit.isBlank(content)) {
throw new IllegalArgumentException("content 不能为空");
}
if (width < 0 || height < 0) {
throw new IllegalArgumentException("width 与 height 不能小于 0");
}
if(StrKit.isBlank(savePath)) {
throw new IllegalArgumentException("savePath 保存地址不能为空");
}
this.content = content;
this.width = width;
this.height = height;
this.errorCorrectionLevel = errorCorrectionLevel;
this.savePath = savePath;
this.urlStr = urlStr;
}

public void render() {
/*response.setHeader("Pragma","no-cache");
response.setHeader("Cache-Control","no-cache");
response.setDateHeader("Expires", 0);
response.setContentType("image/png");*/

Map hints = new HashMap();
hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
hints.put(EncodeHintType.MARGIN, 0); //去掉白色边框,极度重要,否则二维码周围的白边会很宽
if (errorCorrectionLevel != null) {
hints.put(EncodeHintType.ERROR_CORRECTION, errorCorrectionLevel);
}

try {
// MultiFormatWriter 可支持多种格式的条形码,在此直接使用 QRCodeWriter,通过查看源码可知少创建一个对象
// BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, width, height, hints);

QRCodeWriter writer = new QRCodeWriter();
BitMatrix bitMatrix = writer.encode(urlStr+content, BarcodeFormat.QR_CODE, width, height, hints);

// 经测试 200 X 200 大小的二维码使用 "png" 格式只有 412B,而 "jpg" 却达到 15KB
//MatrixToImageWriter.writeToStream(bitMatrix, "png", response.getOutputStream()); // format: "jpg"、"png"
// String realPath = request.getServletContext().getRealPath("") + File.separator;
String realPath = PathKit.getWebRootPath() + File.separator;
File jiaFile = new File(realPath + savePath);// 判断文件夹是否存在,不存在则创建这个文件夹
if (!jiaFile.exists()) {
jiaFile.mkdirs();
}
String filePath = savePath + "/" + content + ".png";
File outputFile = new File(realPath + filePath);
//MatrixToImageWriter.writeToFile(bitMatrix, "png", outputFile);
MatrixToImageWriter.writeToPath(bitMatrix, "png", outputFile.toPath());
}catch (Exception e) {
throw new RenderException(e);
}
}


这么一改的话,一万个二维码文件是压缩后是9M多点,比之前的260多M小了好多好多。用时一分多钟,感觉上面的判断文件夹是否存在那个可以放在外面去会更好点。谢谢指点!

CrazyZH

2019-03-14 09:52

生成文件用多线程处理,一万个图片需要四十秒左右生成。

JFinal

2019-03-14 13:32

@CrazyZH jfinal 的 QrCodeRender 是严格试验过,尽可能保证二维码文件的体积最小,这样无论用于在 html 显示还是生成为文件,体积都非常小

默认大小的二维码生成的图片大小为 412 个字节,已经是极小的体积