feat:增加图片打印接口

This commit is contained in:
石崇礼 2025-01-17 15:15:23 +08:00
parent eecc053eae
commit 1474746864
6 changed files with 377 additions and 0 deletions

10
pom.xml
View File

@ -21,6 +21,8 @@
<hutool.version>5.8.25</hutool.version>
<jna.version>5.14.0</jna.version>
<pdfbox.version>3.0.2</pdfbox.version>
<fastjson.version>1.2.83</fastjson.version>
</properties>
<dependencies>
@ -68,6 +70,14 @@
<artifactId>pdfbox</artifactId>
<version>${pdfbox.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>
</dependencies>
<build>

View File

@ -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 <a href="https://gitee.com/shi-chongli">石头人</a>
* @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);
}
}

View File

@ -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 <a href="https://gitee.com/shi-chongli">石头人</a>
* @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<Void> 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<Void> 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<Void> 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<Void> 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("图片打印成功");
}
}

View File

@ -0,0 +1,59 @@
package com.dpkj.modules.autoReplyPrint.service;
import org.springframework.web.multipart.MultipartFile;
/**
* 图片打印服务接口
*
* @author <a href="https://gitee.com/shi-chongli">石头人</a>
* @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);
}

View File

@ -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 <a href="https://gitee.com/shi-chongli">石头人</a>
* @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);
}
}

View File

@ -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 <a href="https://gitee.com/shi-chongli">石头人</a>
* @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<String> 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("获取文件字节失败");
}
}
}