椒江网站建设578做网站,个人网站建设 开题报告,找柳市做网站,如何制作主页ps:SpringBoot ZXing: 是一个用于生成和解析多种条形码和二维码格式的库。支持多种编码格式#xff0c;包括QR码、Code 128、UPC等。可用于Android、Java#xff08;SE#xff09;、C、JavaScript、.NET、Python等平台和语言的应用。允许开发者在应用程序中集成条形码和二维…ps:SpringBoot ZXing: 是一个用于生成和解析多种条形码和二维码格式的库。支持多种编码格式包括QR码、Code 128、UPC等。可用于Android、JavaSE、C、JavaScript、.NET、Python等平台和语言的应用。允许开发者在应用程序中集成条形码和二维码的扫描、生成和解析功能。ZXing项目提供了一个完成度高的Android应用示例它展示了如何使用库在移动设备上扫描和生成码。开源并在Apache 2.0许可下发布。 QR码: 是一种由日本Denso Wave公司创建的特定二维码格式。能够编码文本信息并因其快速读取能力而得名 “快速反应”Quick Response码。通常用于存储URL、联系信息、纯文本、电话号码等。拥有较高的容错率即使码部分被遮挡也可以识别。常见于广告、产品跟踪、物品标识和手机应用中。不是开源项目但Denso Wave对QR码的专利并未穷追用户费用因此它被广泛采用。
当我们说ZXing与QR码的比较时我们实际上是在比较一个库ZXing和它能处理的一种数据格式Q码。你可以使用ZXing这个库来生成QR码或解析QR码内容而QR码本身是一种信息存储格式。
pxm !--zxing生成二维码--dependencygroupIdcom.google.zxing/groupIdartifactIdcore/artifactIdversion3.3.3/version/dependencyQRCodeUtils /*** ClassName : QRCodeUtil* Description : 二维码工具类*/
Slf4j
public class QRCodeGeneratorUtils {private static final String CHARSET utf-8;private static final String FORMAT_NAME png;// 二维码尺寸private static final int QRCODE_SIZE 400;// LOGO宽度private static final int WIDTH 60;// LOGO高度private static final int HEIGHT 60;/*** 生成包含 标题说明 LOGO 的二维码图片** param mainTitle 主标题 底部显示* param subTitle 副标题 底部显示* param content 二维码内容* param imgPath LOGO文件路径* param needCompress LOGO 是否压缩* return 二维码图片流* throws Exception*/private static BufferedImage createImage(String mainTitle, String subTitle, String content, String imgPath, boolean needCompress) throws Exception {HashtableEncodeHintType, Object hints new HashtableEncodeHintType, Object();hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);hints.put(EncodeHintType.CHARACTER_SET, CHARSET);hints.put(EncodeHintType.MARGIN, 5);BitMatrix bitMatrix new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, QRCODE_SIZE, QRCODE_SIZE 100, hints);int width bitMatrix.getWidth();int height bitMatrix.getHeight();int tempHeight height;// 二维码图片大小 有文字放大boolean notEmptyMainTitle StringUtils.isNotEmpty(mainTitle);if (notEmptyMainTitle) {
// tempHeight 200;}BufferedImage image new BufferedImage(width, tempHeight, BufferedImage.TYPE_INT_RGB);for (int x 0; x width; x) {for (int y 0; y height; y) {image.setRGB(x, y, bitMatrix.get(x, y) ? 0xFF000000 : 0xFFFFFFFF);}}// 插入图片LOGOif (StringUtils.isNotEmpty(imgPath)) {QRCodeGeneratorUtils.insertImage(image, imgPath, needCompress);}//主标题插入文字if (StringUtils.isNotEmpty(subTitle)) {Font font new Font(微软雅黑, Font.BOLD, 24);addFontImage(image, mainTitle, 20, 50, font);}//副标题插入文字if (notEmptyMainTitle) {Font font new Font(微软雅黑, Font.PLAIN, 16);addFontImage(image, subTitle, 70, 20, font);}return image;}/*** 添加 底部图片文字** param source 图片源* param declareText 文字本文*/private static void addFontImage(BufferedImage source, String declareText, int offsetY, int fontHeight, Font font) {//设置文本图片宽高BufferedImage textImage strToImage(declareText, QRCODE_SIZE, fontHeight, font);Graphics2D graph source.createGraphics();//开启文字抗锯齿graph.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);int width textImage.getWidth(null);int height textImage.getHeight(null);Image src textImage;//画图 文字图片最终显示位置 在Y轴偏移量 从上往下算graph.drawImage(src, 0, QRCODE_SIZE - 20, width, height, null);//graph.drawImage(src, 0, offsetY, width, height, null);graph.dispose();}/*** 处理文字大小 生成文字图片** param str* param width* param height* return 文本图片*/private static BufferedImage strToImage(String str, int width, int height, Font font) {BufferedImage textImage new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);Graphics2D g2 (Graphics2D) textImage.getGraphics();//开启文字抗锯齿g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);g2.setBackground(Color.WHITE);g2.clearRect(0, 0, width, height);g2.setPaint(Color.BLACK);FontRenderContext context g2.getFontRenderContext();
// Font font new Font(微软雅黑, Font.BOLD, FONT_SIZE);g2.setFont(font);LineMetrics lineMetrics font.getLineMetrics(str, context);FontMetrics fontMetrics FontDesignMetrics.getMetrics(font);float offset (width - fontMetrics.stringWidth(str)) / 2;float y (height lineMetrics.getAscent() - lineMetrics.getDescent() - lineMetrics.getLeading()) / 2;g2.drawString(str, (int) offset, (int) y);return textImage;}/*** 插入LOGO** param source 二维码图片* param imgPath LOGO图片地址* param needCompress 是否压缩* throws Exception*/private static void insertImage(BufferedImage source, String imgPath, boolean needCompress) throws Exception {File file new File(imgPath);if (!file.exists()) {System.err.println( imgPath 该文件不存在);return;}Image src ImageIO.read(new File(imgPath));int width src.getWidth(null);int height src.getHeight(null);if (needCompress) { // 压缩LOGOif (width WIDTH) {width WIDTH;}if (height HEIGHT) {height HEIGHT;}Image image src.getScaledInstance(width, height, Image.SCALE_SMOOTH);BufferedImage tag new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);Graphics g tag.getGraphics();g.drawImage(image, 0, 0, null); // 绘制缩小后的图g.dispose();src image;}// 插入LOGOGraphics2D graph source.createGraphics();int x (QRCODE_SIZE - width) / 2;int y (QRCODE_SIZE - height) / 2;graph.drawImage(src, x, y, width, height, null);Shape shape new RoundRectangle2D.Float(x, y, width, width, 6, 6);graph.setStroke(new BasicStroke(3f));graph.draw(shape);graph.dispose();}/*** 生成二维码(内嵌LOGO) 本地保存** param content 内容* param imgPath LOGO地址* param destPath 存放目录* param needCompress 是否压缩LOGO* throws Exception*/public static String encode(String content, String imgPath, String destPath, boolean needCompress) throws Exception {BufferedImage image QRCodeGeneratorUtils.createImage(null, null, content, imgPath, needCompress);mkdirs(destPath);// 随机生成二维码图片文件名String file UUID.randomUUID() .jpg;ImageIO.write(image, FORMAT_NAME, new File(destPath / file));return destPath file;}/*** 创建二维码 底部有标题 LOGO** param mainTitle 主标题* param subTitle 副标题* param content 二维码内容* param imgPath 图片地址* param filePath 临时存储本地图片地址* param needCompress LOGO是否压缩 推荐为True*/public static File createTitleImage(String mainTitle, String subTitle, String content, String imgPath, boolean needCompress, String filePath) {try {//创建二维码BufferedImage image QRCodeGeneratorUtils.createImage(mainTitle, subTitle, content, imgPath, needCompress);// 创建目录File directory new File(filePath).getParentFile();if (!directory.exists()) {directory.mkdirs();}// 将图片数据写入文件File outputfile new File(filePath);ImageIO.write(image, FORMAT_NAME, outputfile);// 返回文件对象return outputfile;} catch (Exception e) {log.error(创建二维码异常{}, filePath);throw new RuntimeException(e);}}/*** 创建二维码 底部有标题 LOGO** param mainTitle 主标题* param subTitle 副标题* param content 二维码内容* param imgPath 图片地址* param needCompress LOGO是否压缩 推荐为True* param response 响应流*/public static void createAndDownTitleImage(String mainTitle, String subTitle, String content, String imgPath, boolean needCompress, HttpServletResponse response) {BufferedImage image null;ImageOutputStream imageOutput null;long length 0;try {//创建二维码image QRCodeGeneratorUtils.createImage(mainTitle, subTitle, content, imgPath, needCompress);//步骤一BufferedImage 转 InputStream/*ByteArrayOutputStream byteArrayOutputStream new ByteArrayOutputStream();imageOutput ImageIO.createImageOutputStream(byteArrayOutputStream);ImageIO.write(image, png, imageOutput);*/String filePath C:\\Users\\123\\Downloads\\22222.png;File barcodeFile new File(filePath);ImageIO.write(image, png, barcodeFile);System.out.println(QR码已生成并保存到: filePath);//步骤二获得文件长度/*length imageOutput.length();// 文件名 类型需要注明String fileName 6S-【 title 】点检.png;//设置文件长度response.setContentLength((int) length);//输入流InputStream inputStream new ByteArrayInputStream(byteArrayOutputStream.toByteArray());//步骤三传入文件名、输入流、响应fileDownload(fileName, inputStream, response);*/} catch (Exception e) {throw new RuntimeException(e);}}//文件下载方法工具类public static void fileDownload(String filename, InputStream input, HttpServletResponse response) {try {byte[] buffer new byte[input.available()];input.read(buffer);input.close();// 清空responseresponse.reset();// 设置response的Headerresponse.addHeader(Content-Disposition, attachment;filename new String(filename.getBytes(utf-8), ISO-8859-1));OutputStream toClient new BufferedOutputStream(response.getOutputStream());response.setContentType(application/octet-stream);toClient.write(buffer);toClient.flush();//关闭即下载toClient.close();} catch (Exception e) {e.printStackTrace();}}/*** 当文件夹不存在时mkdirs会自动创建多层目录区别于mkdir(mkdir如果父目录不存在则会抛出异常)** param destPath 存放目录* author lanyuan Email: mmm333zzz520163.com* date 2013-12-11 上午10:16:36*/public static void mkdirs(String destPath) {File file new File(destPath);// 当文件夹不存在时mkdirs会自动创建多层目录区别于mkdir(mkdir如果父目录不存在则会抛出异常)if (!file.exists() || !file.isDirectory()) {file.mkdirs();}}/*** 文件压缩** param filePaths 压缩文件路径* param zipPath zip文件路径*/public static void zip(ListString filePaths, String zipPath) {ZipOutputStream zipOutput null;try {File zipFile new File(zipPath);// 判断文件是否存在如文件不存在创建一个新文件if (!zipFile.exists()) {zipFile.createNewFile();}// 创建一个zip文件输出流zipOutput new ZipOutputStream(new FileOutputStream(zipFile));for (String filePath : filePaths) {File file new File(filePath);// 判断文件是否存在如不存在直接跳过if (!file.exists()) {continue;}/*** 创建一个缓冲读取流提高读取效率* 也可以直接创建一个 FileInputStream 对象BufferedInputStream内部维护了一个8KB的缓冲区BufferedInputStream本身不具备读取能力* BufferedInputStream 可以手动指定缓冲区大小 单位为字节例如new BufferedInputStream(new FileInputStream(file), 10240)*/BufferedInputStream bufferedInput new BufferedInputStream(new FileInputStream(file));// 设置压缩条目名称zipOutput.putNextEntry(new ZipEntry(file.getName()));byte[] bytes new byte[1024];int len -1;// 读取file内的字节流写入到zipOutput内while ((len bufferedInput.read(bytes)) ! -1) {zipOutput.write(bytes, 0, len);}// 关闭输入流// 无需关闭new FileInputStream(file)的输入流 因为BufferedInputStream.close()方法内部已经调用了FileInputStream.close()方法bufferedInput.close();// 写入完毕后关闭条目zipOutput.closeEntry();}} catch (Exception e) {log.info(文件压缩失败{}, e.getMessage(), e);} finally {try {if (zipOutput ! null) {// 写入完毕后关闭条目zipOutput.close();}} catch (Exception e) {log.error(文件压缩关闭流异常,{}, e.getMessage(), e);}}}}IZXService
/*** title IZXService*/
public interface IZXService {/*** 生成包含 标题说明 LOGO 的二维码图片** param mainTitle 主标题 底部显示* param subTitle 副标题 底部显示* param fileName 文件名称* param content 二维码内容* param imgPath LOGO文件路径* param needCompress LOGO 是否压缩* return 二维码图片流* throws Exception*/String createTitleImage(String mainTitle,String subTitle,String fileName, String content, String imgPath, boolean needCompress);}IZXServiceImpl /*** title ZXServiceImpl*/
Service
Slf4j
public class ZXServiceImpl implements IZXService {Value(${qr-code.filePath:})private String filePath;Resourceprivate OssTemplate ossTemplate;/*** 生成包含 标题说明 LOGO 的二维码图片** param mainTitle 主标题 底部显示* param subTitle 副标题 底部显示* param subTitle 文件名称* param content 二维码内容* param imgPath LOGO文件路径* param needCompress LOGO 是否压缩* return 二维码图片流* throws Exception*/Overridepublic String createTitleImage(String mainTitle, String subTitle,String fileName, String content, String imgPath, boolean needCompress) {File file null;SystemOssFile systemOssFile;try {file QRCodeGeneratorUtils.createTitleImage(mainTitle, subTitle, content, imgPath, true,filePathfileName);systemOssFile ossTemplate.putFileReturnOriginalName(file);Assert.notNull(systemOssFile,上传文件失败);}catch (Exception e){log.error(生成二维码异常{},e.getMessage(),e);throw new RuntimeException(生成二维码异常);}finally {if(ObjectUtils.isNotEmpty(file)){file.delete();}}return systemOssFile.getLink();}
}使用
Overridepublic void save(LandInfoForm form) {// 保存// 生成二维码并更新qrCodeString qrCodeName ; // 区县/镇街/村/地块名称String titleImage izxService.createTitleImage(, qrCodeName, qrCodeName - landInfo.getId() .png, String.valueOf(landInfo.getCode()), , true);landInfo.setQrCode(titleImage);baseMapper.updateById(landInfo);}zip包下载
一 Overridepublic void export(LandInfoForm form, HttpServletResponse response) {File codeFile null;FileInputStream fileInputStream null;ListString filepath Collections.synchronizedList(new ArrayList());if (CollectionUtil.isNotEmpty(form.getIdList()) form.getIdList().size() 0) {ListLandInfo landInfoList baseMapper.selectBatchIds(form.getIdList());if (CollectionUtil.isNotEmpty(landInfoList)) {// 生成所有二维码codeFile getFile(filepath, landInfoList);// 一次性打包packIntoPackage(response, codeFile, fileInputStream, filepath);}}}private File getFile(ListString filepath, ListLandInfo list) {//zip文件保存在服务器上的地址String codePath zipPath;File codeFile;//判断是否为文件codeFile new File(codePath);// 判断文件夹是否存在如文件不存在创建一个新文件if (!codeFile.exists()) {codeFile.mkdir();}//生成二维码文件list.parallelStream().forEach(i - {filepath.add(getFilePath(i));});return codeFile;}private String getFilePath(LandInfo landInfo) {String[] split landInfo.getAreaCodes().split(,);if (split.length 5) throw new RuntimeException(地块区域信息不完整);String qrCodeName getSysArea(split[2]) getSysArea(split[3]) getSysArea(split[4]) - landInfo.getName(); // 区县/镇街/村/地块名称return izxService.createQRCodeStream(, qrCodeName, qrCodeName - landInfo.getId() .png, String.valueOf(landInfo.getCode()), , true);}private void packIntoPackage(HttpServletResponse response, File codeFile, FileInputStream fileInputStream, ListString filepath) {//zip文件保存在服务器上的地址String codePath zipPath;try {//打包成zip文件String fileName new StringBuilder(System.currentTimeMillis() ms).append(_code.zip).toString();String zip new StringBuilder(codePath).append(\\).append(fileName).toString();QRCodeGeneratorUtils.zip(filepath, zip);//从该应用服务器下载文件fileInputStream new FileInputStream(zip);downFile(fileInputStream, response, fileName);} catch (Exception e) {log.error(下载失败{}, e.getMessage(), e);throw new RuntimeException(下载失败);} finally {//删除服务器中的文件try {if (fileInputStream ! null) {fileInputStream.close();}//删除二维码FileUtils.forceDelete(codeFile);} catch (Exception e) {log.error(删除二维码zip异常,{}, e.getMessage(), e);}}}public static void downFile(InputStream inputStream, HttpServletResponse response, String fileName) {try {response.reset();response.setContentType(getContentType(fileName));response.setHeader(Content-Disposition, attachment; filename fileName);BufferedOutputStream out new BufferedOutputStream(response.getOutputStream());byte[] buf new byte[1024];int length 0;//不断的读取了文件的资源while ((length inputStream.read(buf)) ! -1) {//向浏览器输出out.write(buf, 0, length);}//关闭 资源out.flush();out.close();inputStream.close();response.flushBuffer();} catch (IOException e) {e.printStackTrace();}}public static String getContentType(String returnFileName) {String contentType application/octet-stream;if (returnFileName.lastIndexOf(.) 0) {return contentType;}returnFileName returnFileName.toLowerCase();returnFileName returnFileName.substring(returnFileName.lastIndexOf(.) 1);if (html.equals(returnFileName) || htm.equals(returnFileName) || shtml.equals(returnFileName)) {contentType text/html;} else if (xls.equals(returnFileName)) {contentType application/vnd.ms-excel;} else if (zip.equals(returnFileName)) {contentType application/zip;}return contentType;}二
文件下载导出解压PostMapping(/getOssFile)
ApiOperationSupport(order 8)
ApiOperation(value 下载, notes 下载)
public RString getOssFile(HttpServletRequest req, HttpServletResponse response, RequestParam(fileName) String fileName){ListHousehold households householdService.getBaseMapper().selectList(Wrappers.lambdaQuery(Household.class).eq(Household::getTenantId, 331003200205).eq(Household::getIsDeleted, 0));ArrayListString keyList new ArrayList();MapString, String hashMap new HashMap();for (Household household : households) {if (StringUtil.isNotBlank(household.getQrCodeImg())){String substring household.getQrCodeImg().substring(47);hashMap.put(substring,household.getHouseholdNo().png);keyList.add(substring);}}//特别注意 这个文件路径 只需要文件路径 不需要带域名之类的 并且文件全路径要和桶名称对应上//keyList.add(upload/20220915/18768cb97623e8e0f36b5f7980ed1720.png);String endpoint http://oss-cn-hangzhou.aliyuncs.com;String accessKeyId LTAI4FeddqmzyunKGQmt36Vx;String accessKeySecret 8xpmbrDgDbunlfjtxA1JsgCAciXKMz;OSSClient ossClient new OSSClient(endpoint, accessKeyId, accessKeySecret);// 创建临时文件File zipFile null;try {//临时文件名称zipFile File.createTempFile(test, .zip);FileOutputStream f new FileOutputStream(zipFile);/*** 作用是为任何OutputStream产生校验和* 第一个参数是制定产生校验和的输出流第二个参数是指定Checksum的类型 Adler32较快和CRC32两种*/CheckedOutputStream csum new CheckedOutputStream(f, new Adler32());// 用于将数据压缩成Zip文件格式ZipOutputStream zos new ZipOutputStream(csum);for (String ossFile : keyList) {// 获取Object返回结果为OSSObject对象OSSObject ossObject ossClient.getObject(meiyun-mng, ossFile);// 读去Object内容 返回InputStream inputStream ossObject.getObjectContent();// 对于每一个要被存放到压缩包的文件都必须调用ZipOutputStream对象的putNextEntry()方法确保压缩包里面文件不同名//String nameossFile.substring(ossFile.lastIndexOf(/)1);String name ;if (hashMap.containsKey(ossFile)){String householdNo hashMap.get(ossFile);name householdNo;}zos.putNextEntry(new ZipEntry(name));int bytesRead 0;// 向压缩文件中输出数据while ((bytesRead inputStream.read()) ! -1) {zos.write(bytesRead);}inputStream.close();zos.closeEntry(); // 当前文件写完定位为写入下一条项目}zos.close();String header req.getHeader(User-Agent).toUpperCase();if (header.contains(MSIE) || header.contains(TRIDENT) || header.contains(EDGE)) {fileName URLEncoder.encode(fileName, utf-8);//IE下载文件名空格变号问题fileName fileName.replace(, %20);} else {fileName new String(fileName.getBytes(), ISO8859-1);}response.reset();response.setContentType(text/plain);response.setContentType(application/octet-stream; charsetutf-8);response.setHeader(Location, fileName);response.setHeader(Cache-Control, max-age0);response.setHeader(Content-Disposition, attachment; filename fileName);FileInputStream fis new FileInputStream(zipFile);BufferedInputStream buff new BufferedInputStream(fis);BufferedOutputStream out new BufferedOutputStream(response.getOutputStream());byte[] car new byte[1024];int l 0;while (l zipFile.length()) {int j buff.read(car, 0, 1024);l j;out.write(car, 0, j);}// 关闭流fis.close();buff.close();out.close();ossClient.shutdown();// 删除临时文件zipFile.delete();} catch (IOException e1) {e1.printStackTrace();}catch (Exception e) {e.printStackTrace();}return R.status(true);
}