From 1474746864224f736e4203f5a359af14b619b9e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=9F=B3=E5=A4=B4=E4=BA=BA?= <3076767823@qq.com> Date: Fri, 17 Jan 2025 15:15:23 +0800 Subject: [PATCH] =?UTF-8?q?feat=EF=BC=9A=E5=A2=9E=E5=8A=A0=E5=9B=BE?= =?UTF-8?q?=E7=89=87=E6=89=93=E5=8D=B0=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 10 +++ .../autoReplyPrint/base/BaseImagePrint.java | 89 +++++++++++++++++++ .../controller/ImagePrintController.java | 78 ++++++++++++++++ .../service/ImagePrintService.java | 59 ++++++++++++ .../impl/USBImagePrintServiceImpl.java | 56 ++++++++++++ .../autoReplyPrint/utils/ImageUtils.java | 85 ++++++++++++++++++ 6 files changed, 377 insertions(+) create mode 100644 src/main/java/com/dpkj/modules/autoReplyPrint/base/BaseImagePrint.java create mode 100644 src/main/java/com/dpkj/modules/autoReplyPrint/controller/ImagePrintController.java create mode 100644 src/main/java/com/dpkj/modules/autoReplyPrint/service/ImagePrintService.java create mode 100644 src/main/java/com/dpkj/modules/autoReplyPrint/service/impl/USBImagePrintServiceImpl.java create mode 100644 src/main/java/com/dpkj/modules/autoReplyPrint/utils/ImageUtils.java diff --git a/pom.xml b/pom.xml index 66e8b55..3f0b1c6 100644 --- a/pom.xml +++ b/pom.xml @@ -21,6 +21,8 @@ 5.8.25 5.14.0 3.0.2 + 1.2.83 + @@ -68,6 +70,14 @@ pdfbox ${pdfbox.version} + + + com.alibaba + fastjson + ${fastjson.version} + + + diff --git a/src/main/java/com/dpkj/modules/autoReplyPrint/base/BaseImagePrint.java b/src/main/java/com/dpkj/modules/autoReplyPrint/base/BaseImagePrint.java new file mode 100644 index 0000000..b19cf0a --- /dev/null +++ b/src/main/java/com/dpkj/modules/autoReplyPrint/base/BaseImagePrint.java @@ -0,0 +1,89 @@ +package com.dpkj.modules.autoReplyPrint.base; + +import com.dpkj.common.exception.RRException; +import com.dpkj.modules.autoReplyPrint.utils.AutoReplyPrint; +import com.dpkj.modules.autoReplyPrint.utils.ImageUtils; +import com.sun.jna.Pointer; +import org.springframework.web.multipart.MultipartFile; + + +/** + * 图片打印基础实现 + * + * @author 石头人 + * @version 1.0 + * @since 2025-01-17 14:37:23 + */ +public abstract class BaseImagePrint { + + /** + * 必须要实现这个,获取句柄 + * @param devName 设备名称 + * @return 窗口句柄 + */ + public abstract Pointer getHandle(String devName); + + + public void printFromPath(String devName, int dstw, int dsth, String pszFile, int binaryzation_method, int compression_method) { + Pointer handle = getHandle(devName); + try { + // 开始打印图片 + boolean printTag = AutoReplyPrint.INSTANCE.CP_Pos_PrintRasterImageFromFile(handle, dstw, dsth, pszFile, binaryzation_method, compression_method); + if( !printTag ){ + throw new RRException("打印图片失败"); + } + + // 切纸 + AutoReplyPrint.INSTANCE.CP_BlackMark_SetBlackMarkPaperCutPosition(handle, 0); + boolean cutPaper = AutoReplyPrint.INSTANCE.CP_Pos_FeedAndHalfCutPaper(handle); + if ( !cutPaper){ + throw new RRException("图片裁剪失败,请自行裁剪"); + } + }catch (Exception e){ + e.printStackTrace(); + throw new RRException(e); + }finally { + if ( handle != null) AutoReplyPrint.INSTANCE.CP_Port_Close(handle); + } + } + + + public void printFromPathData(String devName, int dstw, int dsth, String pszFile, int binaryzation_method, int compression_method) { + // 获取图片 + byte[] data = ImageUtils.imageToBytes(pszFile); + this.printFromData(devName, dstw, dsth, data, binaryzation_method, compression_method); + } + + + public void printFromData(String devName, int dstw, int dsth, byte[] data, int binaryzation_method, int compression_method) { + Pointer handle = getHandle(devName); + try { + // 开始打印图片 + boolean printTag = AutoReplyPrint.INSTANCE.CP_Pos_PrintRasterImageFromData(handle, dstw, dsth, data, data.length, binaryzation_method, compression_method); + if( !printTag ){ + throw new RRException("打印图片失败"); + } + + // 切纸 + AutoReplyPrint.INSTANCE.CP_BlackMark_SetBlackMarkPaperCutPosition(handle, 0); + boolean cutPaper = AutoReplyPrint.INSTANCE.CP_Pos_FeedAndHalfCutPaper(handle); + if ( !cutPaper){ + throw new RRException("图片裁剪失败,请自行裁剪"); + } + }catch (Exception e){ + e.printStackTrace(); + throw new RRException(e); + }finally { + if ( handle != null) AutoReplyPrint.INSTANCE.CP_Port_Close(handle); + } + } + + + public void printFromMultipartFile(String devName, int dstw, int dsth, MultipartFile file, int binaryzation_method, int compression_method){ + byte[] data = ImageUtils.getByteToMultipartFile(file); + this.printFromData(devName, dstw, dsth, data, binaryzation_method, compression_method); + } + + +} + diff --git a/src/main/java/com/dpkj/modules/autoReplyPrint/controller/ImagePrintController.java b/src/main/java/com/dpkj/modules/autoReplyPrint/controller/ImagePrintController.java new file mode 100644 index 0000000..9c97d2e --- /dev/null +++ b/src/main/java/com/dpkj/modules/autoReplyPrint/controller/ImagePrintController.java @@ -0,0 +1,78 @@ +package com.dpkj.modules.autoReplyPrint.controller; + +import com.dpkj.common.vo.Result; +import com.dpkj.modules.autoReplyPrint.service.ImagePrintService; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.multipart.MultipartFile; + +import javax.annotation.Resource; + +/** + * 图片打印控制层 + * + * @author 石头人 + * @version 1.0 + * @since 2025-01-17 13:57:11 + */ +@RequestMapping("/autoReplyPrint") +public class ImagePrintController { + + @Resource(name = "USBImagePrint") + private ImagePrintService usbImagePrintService; + + /** + * 图片打印,通过路径 + */ + @GetMapping("/usb/imagePrint/path") + Result usbImagePrintFromPath(@RequestParam(defaultValue = "VID:0x0FE6,PID:0x811E") String usbName, + @RequestParam(defaultValue = "500") Integer width, + @RequestParam(defaultValue = "500") Integer height, + @RequestParam String path, Integer binaryMethod, Integer compressionMethod){ + this.usbImagePrintService.imagePrintFromPath(usbName, width, height, path, binaryMethod, compressionMethod); + return Result.ok("图片打印成功"); + } + + + /** + * 图片打印,通过byte[] + */ + @GetMapping("/usb/imagePrint/pathData") + Result usbImagePrintFromData(@RequestParam(defaultValue = "VID:0x0FE6,PID:0x811E") String usbName, + @RequestParam(defaultValue = "500") Integer width, + @RequestParam(defaultValue = "500") Integer height, + @RequestParam String path, Integer binaryMethod, Integer compressionMethod){ + this.usbImagePrintService.imagePrintFromPathData(usbName, width, height, path, binaryMethod, compressionMethod); + return Result.ok("图片打印成功"); + } + + + /** + * 图片打印,通过multipartFile文件 + */ + @GetMapping("/usb/imagePrint/multipartFile") + Result usbImagePrintFromData(@RequestParam(defaultValue = "VID:0x0FE6,PID:0x811E") String usbName, + @RequestParam(defaultValue = "500") Integer width, + @RequestParam(defaultValue = "500") Integer height, + @RequestParam MultipartFile file, Integer binaryMethod, Integer compressionMethod){ + this.usbImagePrintService.imagePrintFromMultipartFile(usbName, width, height, file, binaryMethod, compressionMethod); + return Result.ok("图片打印成功"); + } + + + /** + * 图片打印,通过byte[] + */ + @GetMapping("/usb/imagePrint/data") + Result usbImagePrintFromData(@RequestParam(defaultValue = "VID:0x0FE6,PID:0x811E") String usbName, + @RequestParam(defaultValue = "500") Integer width, + @RequestParam(defaultValue = "500") Integer height, + @RequestParam byte[] data, Integer binaryMethod, Integer compressionMethod){ + this.usbImagePrintService.imagePrintFromData(usbName, width, height, data, binaryMethod, compressionMethod); + return Result.ok("图片打印成功"); + } + + +} + diff --git a/src/main/java/com/dpkj/modules/autoReplyPrint/service/ImagePrintService.java b/src/main/java/com/dpkj/modules/autoReplyPrint/service/ImagePrintService.java new file mode 100644 index 0000000..e823ceb --- /dev/null +++ b/src/main/java/com/dpkj/modules/autoReplyPrint/service/ImagePrintService.java @@ -0,0 +1,59 @@ +package com.dpkj.modules.autoReplyPrint.service; + +import org.springframework.web.multipart.MultipartFile; + +/** + * 图片打印服务接口 + * + * @author 石头人 + * @version 1.0 + * @since 2025-01-17 11:38:36 + */ +public interface ImagePrintService { + + /** + * 图片打印 + * @param devName 设备名称/usb/tcp/com + * @param dstw 要打印的宽度 + * @param dsth 要打印的高度 + * @param pszFile 图片的路径 + * @param binaryzation_method 图片二值化算法。0 表示抖动算法,1 表示阀值算法,2 表示误差扩散法。具体效果请测试查看。 + * @param compression_method 最终打印数据的压缩方式,各值定义如下:0 不压缩,1 一级压缩,2 二级压缩。 + */ + void imagePrintFromPath(String devName, int dstw, int dsth, String pszFile, int binaryzation_method, int compression_method); + + /** + * 图片打印,内部直接读取转换为byte进行打印 + * @param devName 设备名称/usb/tcp/com + * @param dstw 要打印的宽度 + * @param dsth 要打印的高度 + * @param pszFile 图片的路径 + * @param binaryzation_method 图片二值化算法。0 表示抖动算法,1 表示阀值算法,2 表示误差扩散法。具体效果请测试查看。 + * @param compression_method 最终打印数据的压缩方式,各值定义如下:0 不压缩,1 一级压缩,2 二级压缩。 + */ + void imagePrintFromPathData(String devName, int dstw, int dsth, String pszFile, int binaryzation_method, int compression_method); + + /** + * 直接传输数据进行打印 + * @param devName 设备名称/usb/tcp/com + * @param dstw 要打印的宽度 + * @param dsth 要打印的高度 + * @param data 图片数据 + * @param binaryzation_method 图片二值化算法。0 表示抖动算法,1 表示阀值算法,2 表示误差扩散法。具体效果请测试查看。 + * @param compression_method 最终打印数据的压缩方式,各值定义如下:0 不压缩,1 一级压缩,2 二级压缩。 + */ + void imagePrintFromData(String devName, int dstw, int dsth, byte[] data, int binaryzation_method, int compression_method); + + /** + * 直接传的MultipartFile文件过来 + * @param devName 设备名称/usb/tcp/com + * @param dstw 要打印的宽度 + * @param dsth 要打印的高度 + * @param file 图片数据 + * @param binaryzation_method 图片二值化算法。0 表示抖动算法,1 表示阀值算法,2 表示误差扩散法。具体效果请测试查看。 + * @param compression_method 最终打印数据的压缩方式,各值定义如下:0 不压缩,1 一级压缩,2 二级压缩。 + */ + void imagePrintFromMultipartFile(String devName, int dstw, int dsth, MultipartFile file, int binaryzation_method, int compression_method); + + +} diff --git a/src/main/java/com/dpkj/modules/autoReplyPrint/service/impl/USBImagePrintServiceImpl.java b/src/main/java/com/dpkj/modules/autoReplyPrint/service/impl/USBImagePrintServiceImpl.java new file mode 100644 index 0000000..6c69750 --- /dev/null +++ b/src/main/java/com/dpkj/modules/autoReplyPrint/service/impl/USBImagePrintServiceImpl.java @@ -0,0 +1,56 @@ +package com.dpkj.modules.autoReplyPrint.service.impl; + +import com.dpkj.common.exception.RRException; +import com.dpkj.modules.autoReplyPrint.base.BaseImagePrint; +import com.dpkj.modules.autoReplyPrint.service.ImagePrintService; +import com.dpkj.modules.autoReplyPrint.utils.AutoReplyPrint; +import com.sun.jna.Pointer; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; + + +/** + * 图片打印服务 + * + * @author 石头人 + * @version 1.0 + * @since 2025-01-17 11:38:36 + */ +@Slf4j +@Service("USBImagePrint") +public class USBImagePrintServiceImpl extends BaseImagePrint implements ImagePrintService { + + @Override + public Pointer getHandle(String devName) { + try { + return AutoReplyPrint.INSTANCE.CP_Port_OpenUsb(devName, 1); + }catch (Exception e){ + e.printStackTrace(); + throw new RRException("获取USB句柄失败"); + } + } + + @Override + public void imagePrintFromPath(String devName, int dstw, int dsth, String pszFile, int binaryzation_method, int compression_method) { + super.printFromPath(devName, dstw, dsth, pszFile, binaryzation_method, compression_method); + } + + @Override + public void imagePrintFromPathData(String devName, int dstw, int dsth, String pszFile, int binaryzation_method, int compression_method) { + super.printFromPathData(devName, dstw, dsth, pszFile, binaryzation_method, compression_method); + } + + @Override + public void imagePrintFromData(String devName, int dstw, int dsth, byte[] data, int binaryzation_method, int compression_method) { + super.printFromData(devName, dstw, dsth, data, binaryzation_method, compression_method); + } + + @Override + public void imagePrintFromMultipartFile(String devName, int dstw, int dsth, MultipartFile file, int binaryzation_method, int compression_method) { + super.printFromMultipartFile(devName, dstw, dsth, file, binaryzation_method, compression_method); + } + + +} + diff --git a/src/main/java/com/dpkj/modules/autoReplyPrint/utils/ImageUtils.java b/src/main/java/com/dpkj/modules/autoReplyPrint/utils/ImageUtils.java new file mode 100644 index 0000000..f358ea2 --- /dev/null +++ b/src/main/java/com/dpkj/modules/autoReplyPrint/utils/ImageUtils.java @@ -0,0 +1,85 @@ +package com.dpkj.modules.autoReplyPrint.utils; + +import com.dpkj.common.exception.RRException; +import org.springframework.web.multipart.MultipartFile; + +import java.io.BufferedInputStream; +import java.io.ByteArrayOutputStream; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.List; + +/** + * 图片转换工具 + * + * @author 石头人 + * @version 1.0 + * @since 2025-01-17 14:06:09 + */ +public class ImageUtils { + + /** + * 读取图片并转换为byte数组 + * @param imagePath 图片路径 + * @return byte数组 + */ + public static byte[] imageToBytes(String imagePath) { + try (BufferedInputStream bis = new BufferedInputStream(Files.newInputStream(Paths.get(imagePath))); + ByteArrayOutputStream baos = new ByteArrayOutputStream()) { + + byte[] buffer = new byte[4096]; + int bytesRead; + while ((bytesRead = bis.read(buffer)) != -1) { + baos.write(buffer, 0, bytesRead); + } + + return baos.toByteArray(); + } catch (Exception e) { + e.printStackTrace(); + throw new RRException("读取图片信息失败"); + } + } + + + /** + * 获取文件byte[],通过 MultipartFile + * @param file 文件信息 + * @return byte数组 + */ + public static byte[] getByteToMultipartFile(MultipartFile file){ + // 验证文件是否为空 + if (file.isEmpty()) { + throw new RRException("文件内容为空"); + } + + // 验证文件类型 + String contentType = file.getContentType(); + if (contentType == null || !contentType.startsWith("image/")) { + throw new RRException("只支持图片文件"); + } + + // 获取文件扩展名 + String fileName = file.getOriginalFilename(); + String fileExtension = fileName != null ? + fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase() : ""; + + // 验证扩展名 + List allowedExtensions = Arrays.asList("jpg", "jpeg", "png", "gif"); + if (!allowedExtensions.contains(fileExtension)) { + throw new RRException("不支持的文件格式"); + } + + try { + // 转换为字节数组 + return file.getBytes(); + }catch (Exception e){ + e.printStackTrace(); + throw new RRException("获取文件字节失败"); + } + } + + + +} +