1. Graphics2D 图片绘写
我的需求是在图片的固定位置绘写固定数值所以比较简单
ImageIO.write(read, “png”, destImageFile); png是文件类型,我这里是固定的
public class ImageText {
private String data;
private float x;
private float y;
private Font font;
private Color color;
public ImageText(String data, Color color) {
this.data = data;
this.color = color;
}
public ImageText(String data, float x, float y, Font font, Color color) {
this.data = data;
this.x = x;
this.y = y;
this.font = font;
this.color = color;
}
public ImageText() {}
}
public class DrawUtil {
private static final Logger log = LoggerFactory.getLogger(DrawUtil.class);
/**
* JAVA添加文字水印
* @param srcImageFile 目标图片
* @param destImageFile 结果图片
* @param imageTextList 文字及坐标集合
* @return
*/
public static boolean drawText(InputStream srcImageFile, File destImageFile, ArrayList<ImageText> imageTextList) {
try {
//使用ImageIO的read方法读取图片
BufferedImage read = ImageIO.read(srcImageFile);
Graphics2D graphics = read.createGraphics();
// 设置“抗锯齿”的属性
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
for (ImageText imageText : imageTextList) {
// 设置字体类型和大小
graphics.setFont(imageText.getFont());
// 设置颜色
graphics.setColor(imageText.getColor());
// 添加文字
graphics.drawString( imageText.getData(), imageText.getX(), imageText.getY());
}
//回收 Graphics 释放资源
graphics.dispose();
//获取到文件的后缀名
// String fileName = IdUtils.fastSimpleUUID()+".png";
// String formatName = fileName.substring(fileName.lastIndexOf(".") + 1);
//使用ImageIO的write方法进行输出
ImageIO.write(read, "png", destImageFile);
} catch (IOException e) {
log.error(" watermarkText 图文绘制异常!", e);
}
return true;
}
}
2. 获取自定义字体
字体文件存放在resources/static/OPPOSans-B-2.ttf
fontFile.getInputStream() 使用文件流不然报错 找不到文件
fontFile.getFile()本地执行成功但是上服务器就会报错
/**
* 获取字体文件
*/
public static Font getFont(float fontSize) {
Font font = null;
ClassPathResource fontFile = new ClassPathResource("/static/OPPOSans-B-2.ttf");
Font tempFont = null;
try (InputStream in=fontFile.getInputStream();){
tempFont = Font.createFont(Font.TRUETYPE_FONT, in);
} catch (FontFormatException | IOException e) {
log.error(" OPPOSans 字体文件获取失败!", e);
}
assert tempFont != null;
font = tempFont.deriveFont(fontSize);
return font;
}
3. 将File转换MultipartFile
主要是公共的上传文件组件一般使用MultipartFile类型,所有做个转换
MultipartFileDto multipartFileDto = new MultipartFileDto(tempFile.getName(), tempFile.getName(), “image/png”, fileInputStream);
“image/png”, 配置是为了上传MinIO返回的url是直接预览,而不是附件下载
整体图片绘制逻辑是:
先读取resources下的固定图片文件,同时创建临时图片文件作为输出对象,将绘制数据和两个文件相关对象传递给drawText绘画。然后 临时文件将File转换MultipartFile上传MinIO返回url保存,删除临时文件
import org.springframework.util.FileCopyUtils;
import org.springframework.web.multipart.MultipartFile;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
public class MultipartFileDto implements MultipartFile {
private final String name;
private String originalFilename;
private String contentType;
private final byte[] content;
public MultipartFileDto(String name, byte[] content) {
this(name, "", null, content);
}
public MultipartFileDto(String name, InputStream contentStream) throws IOException {
this(name, "", null, FileCopyUtils.copyToByteArray(contentStream));
}
public MultipartFileDto(String name, String originalFilename, String contentType, byte[] content) {
this.name = name;
this.originalFilename = (originalFilename != null ? originalFilename : "");
this.contentType = contentType;
this.content = (content != null ? content : new byte[0]);
}
public MultipartFileDto(String name, String originalFilename, String contentType, InputStream contentStream)
throws IOException {
this(name, originalFilename, contentType, FileCopyUtils.copyToByteArray(contentStream));
}
@Override
public String getName() {
return this.name;
}
@Override
public String getOriginalFilename() {
return this.originalFilename;
}
@Override
public String getContentType() {
return this.contentType;
}
@Override
public boolean isEmpty() {
return (this.content.length == 0);
}
@Override
public long getSize() {
return this.content.length;
}
@Override
public byte[] getBytes() throws IOException {
return this.content;
}
@Override
public InputStream getInputStream() throws IOException {
return new ByteArrayInputStream(this.content);
}
@Override
public void transferTo(File dest) throws IOException, IllegalStateException {
FileCopyUtils.copy(this.content, dest);
}
}
/**
* 新增图片消息
*/
private void addImgMsg(JcWechatAccount account, File tempFile) {
//上传图片
try (FileInputStream fileInputStream = new FileInputStream(tempFile);) {
//application/octet-stream 告诉浏览器这是一个附件,浏览器会直接进行下载,而不是预览,只有image/png或者image/jpeg这种的的才会进行预览
MultipartFileDto multipartFileDto = new MultipartFileDto(tempFile.getName(), tempFile.getName(),
"image/png",
fileInputStream);
String upload = commonController.upload(multipartFileDto);
addImgMsgText(account, upload,MessageType.IMAGE);
} catch (Exception e) {
log.error(" MultipartFileDto 文件转换失败!", e);
} finally {
//删除临时文件
tempFile.delete();
}
}
4. 若依多Sheet页excel内部生成用于上传,而不是直接下载返回
搜索若依多Sheet页 会找到相关代码 关键方法改造exportExcelManySheet 也是临时文件的方法,记得删除
/**
* 对list数据源将其里面的数据导入到excel表单
*
* @param list 导出数据集合
* @return 结果
* @throws IOException
*/
public File exportExcelManySheet( List<ExcelExp> list) {
File tempFile = null;
FileOutputStream out = null;
try {
String filename = IdUtils.fastSimpleUUID();
//创建临时文件
tempFile = File.createTempFile(filename, ".xlsx");
out = new FileOutputStream(tempFile);
createWorkbook();
for (int index = 0; index < list.size(); index++) {
this.clazz = list.get(index).getClazz();
this.init(list.get(index).getDataset(), list.get(index).getFileName(), Type.EXPORT);
// 取出一共有多少个sheet.
// double sheetNo = Math.ceil(list.size() / sheetSize);
createSheetManySheet(index);
// 产生一行
Row row = sheet.createRow(0);
int column = 0;
// 写入各个字段的列头名称
for (Object[] os : fields) {
Excel excel = (Excel) os[1];
this.createCell(excel, row, column++);
}
if (Type.EXPORT.equals(type)) {
fillExcelData(index, row);
addStatisticsRow();
}
}
wb.write(out);
// return tempFile;
} catch (IOException e) {
log.error("导出Excel异常{}", e.getMessage());
} finally {
IOUtils.closeQuietly(wb);
IOUtils.closeQuietly(out);
}
return tempFile;
}