当前位置: 首页 > news >正文

制作商城网站模板免费织梦导航网站模板下载地址

制作商城网站模板,免费织梦导航网站模板下载地址,搜索广告是什么,免费永久网站注册前言#xff1a; 在公司做开发时#xff0c;遇到一个需求#xff0c;要求上传的文件有图片#xff0c;也有word和pdf。预览信息时#xff0c;既要求能水印展示出来#xff0c;又要求能大图水印预览。思索许久#xff0c;我决定采取全部打水印然后转成图片Base64#x…前言 在公司做开发时遇到一个需求要求上传的文件有图片也有word和pdf。预览信息时既要求能水印展示出来又要求能大图水印预览。思索许久我决定采取全部打水印然后转成图片Base64但是后面突然发现word不能直接转为图片强制转换会有内容丢失于是我打算先把word转为pdf然后再把pdf转为图片Base64思路堪称完美。 思路有了那该选什么工具好呢网上的教程参差不齐有的工具也能用但是转出来的效果不尽人意在寻找许久后我选择了document4j这工具在转换方面堪称完美但美中不足的是只能在Windows上使用最后我选择了libreoffice。 libreoffice既兼容Windows同时又兼容Linux转换出来的效果也不错于是我的工具问题也就迎刃而解了。 环境 IntelliJ IDEA 2024.1.4 Linux服务器 Windows笔记本 Oracle数据库Mysql数据也行我这里测试用的Mysql LibreOffice 24.2.4 下载地址下载 LibreOffice | LibreOffice 简体中文官方网站 - 自由免费的办公套件 1.安装教程 我们需要下载两个LibreOffice 24.2.4一个是Windows的一个是Linux的。另外下载的话选择国内镜像下载比较快 Window下载完成后安装在D盘即可选择安装没有特别需要注意的安装完自己记得路径就行。对于Linux安装安装如下 1.1解压压缩包 上传到linux指定目录下或者用wget直接下载到linux指定目录下后我上传到的是/opt目录下使用下面命令解压 cd /opt tar -xvf LibreOffice_24.2.4_Linux_x86-64_rpm.tar.gz1.2安装libreoffice 执行下面命令开始安装等待安装完成即可 sudo yum install ./LibreOffice_24.2.4_Linux_x86-64_rpm/RPMS/*.rpm1.3启动libreoffice Windows的话cmd执行下面命令启动其中D:Program FilesLibreOffice就是安装的路径 D:Program FilesLibreOfficeprogramsoffice.exe --headless --invisible --nologo --nodefault --nofirststartwizard --acceptsocket,host127.0.0.1,port8100;urp;Linux的话执行下面命令启动同样的/opt/libreoffice24.2就是安装的路径 /opt/libreoffice24.2/program/soffice --headless --invisible --nologo --nodefault --nofirststartwizard --acceptsocket,host127.0.0.1,port8100;urp;Linux的话还可以使用docker部署这样的话就可以不用安装并启动得那么麻烦使用的镜像是libreoffice/online但是要把这个安装的libreoffice映射出来我这里就不详细介绍了感兴趣的可以自己去试一试。 到此Windows的安装启动就结束了但是Linux还没有结束因为Linux缺少中文字体的缘故导致转出来的中文会是如下的效果 为此我们要给Linux装上中文字体 1.4Linux安装中文字体 首先安装fontconfig yum -y install fontconfig进入/usr/share目录下执行ls会发现这两个目录则说明安装成功 cd /usr/share ls接着打开这个fonts文件夹新建一个叫chinese文件夹 cd fonts mkdir chinese然后将Windows系统的字体文件全部拷进去这里直接复制是不允许的需要复制C:Windows下的Fonts目录到桌面然后再从桌面双击进入Fonts文件夹CtrlA全选上传到服务器的这个chinese目录下 接着给这个目录赋予权限执行命令 chmod -R 755 /usr/share/fonts/chinese安装ttmkfdir编辑配置文件执行命令 yum -y install ttmkfdir ttmkfdir -e /usr/share/X11/fonts/encodings/encodings.dir vi /etc/fonts/fonts.conf在Font directory list配置项下把这个中文字体目录加进去添加如下代码 dir/usr/share/fonts/chinese/dir保存退出后执行下面命令刷新一下缓存 fc-cache到此中文字体安装完成。转出的效果也变成了如下图中文字体也能正常显示了 2.Springboot集成libreoffice 环境安装好了解下来我们就开始写代码了。 2.1引入pom依赖 首先创建完Springboot项目后安装必要的依赖其中重点就是jodconverter-spring-boot-starter和jodconverter-local其他的看需要引入 !--office转换工具--dependencygroupIdorg.jodconverter/groupIdartifactIdjodconverter-spring-boot-starter/artifactIdversion4.4.7/version/dependencydependencygroupIdorg.jodconverter/groupIdartifactIdjodconverter-local/artifactIdversion4.4.7/version/dependency!--pdfbox--dependencygroupIdorg.apache.pdfbox/groupIdartifactIdpdfbox/artifactIdversion2.0.24/version/dependency!--hutool--dependencygroupIdcn.hutool/groupIdartifactIdhutool-all/artifactIdversion5.8.25/version/dependency!--Apache Commons--dependencygroupIdorg.apache.commons/groupIdartifactIdcommons-collections4/artifactIdversion4.4/version/dependencydependencygroupIdcommons-io/groupIdartifactIdcommons-io/artifactIdversion2.16.1/version/dependencydependencygroupIdorg.apache.commons/groupIdartifactIdcommons-lang3/artifactIdversion3.12.0/version/dependency!--Apache Poi--dependencygroupIdorg.apache.poi/groupIdartifactIdpoi-ooxml/artifactIdversion5.2.5/version/dependency!--itextpdf--dependencygroupIdcom.itextpdf/groupIdartifactIditextpdf/artifactIdversion5.5.13.4/version/dependency2.2修改yaml配置文件 修改application.yaml添加如下配置 spring:profiles:active: local# 共享配置 jodconverter:local:enabled: trueportNumbers: 8100maxTasksPerProcess: 100taskQueueTimeout: 60file:path:windows: D:/temp/filelinux: /file--- spring:config:activate:on-profile: local jodconverter:local:officeHome: D:Program FilesLibreOffice --- spring:config:activate:on-profile: server jodconverter:local:officeHome: /opt/libreoffice24.2其中我用spring: profiles: active: 来区分是Windows启动的项目还是Linux若是Windows则改为local若是Linux的话改成server即可 file:path:是文件上传后保存的目录。若是Linux环境确保启动该项目的用户对该目录有足够的读写权限否则上传文件会报错500。 2.3control层代码 FileControl.java完整代码如下 package com.example.testdemo.test.control;import com.example.testdemo.test.model.DownloadFile; import com.example.testdemo.test.service.FileService; import com.example.testdemo.test.utils.Result; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile;import javax.annotation.Resource; import javax.servlet.http.HttpServletResponse;/*** 项目名称: testDemo* 作者: zhaojs* 创建日期: 2024年07月04日* 文件说明: 文件控制层*/ RestController public class FileControl {/*** 文件服务*/Resourceprivate FileService fileService;/*** 文件上传* param files* return*/PostMapping(/file/upload)public Result uploadFile(RequestParam(files) MultipartFile[] files) {return fileService.uploadFile(files);}/*** 获取文件列表* param ids* return*/GetMapping(/file/getFile/{ids})public Result getFile(PathVariable(ids) String ids) {return Result.success(fileService.getFile(ids));}/*** 附件转为图片的base64编码* 支持附件类型doc、docx、pdf、png、jpeg* param downloadFile*/PostMapping(/file/switchAttachment/imageBase64)public Result switchAttachmentImageBase64(RequestBody DownloadFile downloadFile) {return fileService.switchAttachmentImageBase64(downloadFile);} }2.4service层代码 FileService.java完整代码如下 package com.example.testdemo.test.service;import com.example.testdemo.test.model.Attachment; import com.example.testdemo.test.model.DownloadFile; import com.example.testdemo.test.utils.Result; import org.springframework.web.multipart.MultipartFile;import javax.servlet.http.HttpServletResponse; import java.util.List;/*** 项目名称: testDemo* 创建日期: 2024年07月04日* author zhaojs* 文件说明: 见类描述*/ public interface FileService {/*** 上传文件* param files* return*/Result uploadFile(MultipartFile[] files);/*** 获取文件列表* param ids* return*/ListAttachment getFile(String ids);/*** 附件转为图片的base64编码* param downloadFile* return*/Result switchAttachmentImageBase64(DownloadFile downloadFile); }FileServiceImpl.java完整代码如下 package com.example.testdemo.test.service.Impl;import com.example.testdemo.test.dao.AttachmentDao; import com.example.testdemo.test.model.Attachment; import com.example.testdemo.test.model.DownloadFile; import com.example.testdemo.test.service.FileService; import com.example.testdemo.test.utils.Result; import com.example.testdemo.test.utils.WordWaterMarker; import com.itextpdf.text.Element; import com.itextpdf.text.pdf.BaseFont; import com.itextpdf.text.pdf.PdfContentByte; import com.itextpdf.text.pdf.PdfGState; import com.itextpdf.text.pdf.PdfReader; import com.itextpdf.text.pdf.PdfStamper; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.MapUtils; import org.apache.commons.io.FilenameUtils; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.rendering.ImageType; import org.apache.pdfbox.rendering.PDFRenderer; import org.apache.poi.xwpf.usermodel.XWPFDocument; import org.jodconverter.core.DocumentConverter; import org.jodconverter.core.document.DefaultDocumentFormatRegistry; import org.jodconverter.core.document.DocumentFormat; import org.jodconverter.core.office.OfficeException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.core.io.FileSystemResource; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile;import javax.annotation.Resource; import javax.imageio.ImageIO; import javax.imageio.stream.ImageOutputStream; import javax.servlet.http.HttpServletResponse; import java.awt.*; import java.awt.geom.AffineTransform; import java.awt.image.BufferedImage; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.StandardCopyOption; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.ZoneId; import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.Arrays; import java.util.Base64; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.UUID; import java.util.concurrent.Callable; import java.util.concurrent.ConcurrentSkipListSet; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream;Service public class FileServiceImpl implements FileService {/*** Windows文件路径*/Value(${file.path.windows})private String filePathWindows;/*** Linux文件路径*/Value(${file.path.linux})private String filePathLinux;/*** 文档转换器*/Resourceprivate DocumentConverter documentConverter;/*** 附件表Dao*/Resourceprivate AttachmentDao attachmentDao;/*** 日期时间格式*/private static final DateTimeFormatter DATE_TIME_FORMATTER DateTimeFormatter.ofPattern(yyyyMMddHHmmssSSS);/*** 并发处理任务的数量*/private static final int MAX_CONCURRENT_TASKS 5;/*** 日志*/private static final Logger logger LoggerFactory.getLogger(FileServiceImpl.class);/*** 上传文件** param files* return*/Overridepublic Result uploadFile(MultipartFile[] files) {try {// 遍历文件数组并处理每个文件for (MultipartFile file : files) {if (! file.isEmpty()) {// 处理文件名String originalFilename file.getOriginalFilename();String extension FilenameUtils.getExtension(originalFilename);String uniqueFilename UUID.randomUUID().toString() (extension ! null ! extension.isEmpty() ? . extension : );// 获取当前日期并格式化为年月目录格式LocalDate now LocalDate.now();DateTimeFormatter formatter DateTimeFormatter.ofPattern(yyyy/MM);String yearMonthDir now.format(formatter);// 指定保存的根目录对于Windows可以是D盘的某个路径对于Linux通常是/home/user或特定的目录String rootDir System.getProperty(os.name).toLowerCase().startsWith(win) ? filePathWindows : filePathLinux;// 构建保存文件的完整路径使用Paths.get()自动处理路径分隔符Path directoryPath Paths.get(rootDir, yearMonthDir);// 确保目录存在Files.createDirectories(directoryPath);// 文件保存路径Path filePath directoryPath.resolve(uniqueFilename);// 将文件输入流中的数据复制到目标路径如果目标文件已存在则覆盖原有文件Files.copy(file.getInputStream(), filePath, StandardCopyOption.REPLACE_EXISTING);// 插入附件表Attachment attachment new Attachment();attachment.setAttachmentId(UUID.randomUUID().toString());attachment.setFileId(uniqueFilename);attachment.setFileName(originalFilename);attachment.setFileType(file.getContentType());attachment.setFileSize(Double.valueOf(file.getSize()));attachment.setFilePath(filePath.toString());attachment.setCreateTime(LocalDateTime.now());attachmentDao.insert(attachment);} else {return Result.fail(文件为空);}}return Result.success(文件上传成功);} catch (IOException e) {return Result.fail(文件上传失败);}}/*** 获取文件列表** param ids* return*/Overridepublic ListAttachment getFile(String ids) {if (StringUtils.isNotBlank(ids)) {String[] attachmentIds ids.split(,);ListAttachment attachmentList attachmentDao.selectBatchIds(Arrays.asList(attachmentIds));return attachmentList;}return null;}/*** 附件转为图片的base64编码** param downloadFile* return*/Overridepublic Result switchAttachmentImageBase64(DownloadFile downloadFile) {ListMapString, String fileList new ArrayList();ListAttachment attachmentList getFile(downloadFile.getAttachmentIds());attachmentList.forEach(attachment - {MapString, String map new HashMap();map.put(fileName, attachment.getFileName());map.put(filePath, attachment.getFilePath());fileList.add(map);});//附件归类ListString imageFilePathList new ArrayList();ListString pdfFilePathList new ArrayList();ListString wordFilePathList new ArrayList();fileList.forEach(map - {// 附件名称String fileName MapUtils.getString(map, fileName);// 判断附件类型String filePath MapUtils.getString(map, filePath);if (fileName.endsWith(.jpg) || fileName.endsWith(.jpeg) || fileName.endsWith(.png)) {imageFilePathList.add(filePath);} else if (fileName.endsWith(.pdf)) {pdfFilePathList.add(filePath);} else if (fileName.endsWith(.doc) || fileName.endsWith(.docx)) {wordFilePathList.add(filePath);}});ListString imageBase64List new ArrayList();//先把word转为图片base64编码if (CollectionUtils.isNotEmpty(wordFilePathList)) {ListString imageBase64 wordFileToImageBase64(wordFilePathList, downloadFile.getWatermarkText());if (imageBase64 ! null ! imageBase64.isEmpty()) {imageBase64List.addAll(imageBase64);}}//再把pdf转为图片base64编码if (CollectionUtils.isNotEmpty(pdfFilePathList)) {ListString imageBase64 pdfFileToImageBase64(pdfFilePathList, downloadFile.getWatermarkText());if (imageBase64 ! null ! imageBase64.isEmpty()) {imageBase64List.addAll(imageBase64);}}//最后把图片直接转为base64编码if (CollectionUtils.isNotEmpty(imageFilePathList)) {ListString imageBase64 imageFileToBase64(imageFilePathList, downloadFile.getWatermarkText());if (imageBase64 ! null ! imageBase64.isEmpty()) {imageBase64List.addAll(imageBase64);}}return Result.success(imageBase64List);}/*** word转为图片base64编码** param wordFilePathList* param watermarkText* return*/public ListString wordFileToImageBase64(ListString wordFilePathList, String watermarkText) {ListString imageBase64List new ArrayList();ExecutorService executor Executors.newFixedThreadPool(MAX_CONCURRENT_TASKS);try {ListFutureListString futures new ArrayList();// 首先将Word文件转换为PDF字节流并为每个字节流创建一个转换任务for (String filePath : wordFilePathList) {// 将Word转换为PDF字节流ByteArrayOutputStream pdfByteStream wordToPdf(filePath);// 将PDF字节流转换为图片Base64CallableListString task () - pdfByteToImageBase64Single(pdfByteStream.toByteArray(), watermarkText);futures.add(executor.submit(task));}// 收集所有任务的结果for (FutureListString future : futures) {try {// 合并每个任务返回的Base64编码图像字符串列表imageBase64List.addAll(future.get());} catch (InterruptedException | ExecutionException e) {Thread.currentThread().interrupt();logger.error(处理PDF字节流时发生错误, e);}}} finally {executor.shutdown();try {if (! executor.awaitTermination(60, TimeUnit.SECONDS)) {executor.shutdownNow();}} catch (InterruptedException e) {executor.shutdownNow();Thread.currentThread().interrupt();logger.error(关闭线程池时发生中断, e);}}return imageBase64List;}/*** word转pdf** param wordFilePath* return* throws Exception*/public ByteArrayOutputStream wordToPdf(String wordFilePath) {ByteArrayOutputStream pdfOutputStream new ByteArrayOutputStream();try (InputStream docxInputStream new FileInputStream(wordFilePath)) {DocumentFormat type docx.equals(getFileType(new File(wordFilePath))) ? DefaultDocumentFormatRegistry.DOCX : DefaultDocumentFormatRegistry.DOC;documentConverter.convert(docxInputStream).as(type).to(pdfOutputStream).as(DefaultDocumentFormatRegistry.PDF).execute();} catch (IOException | OfficeException e) {logger.error(转换Word文件为PDF时发生错误, e);throw new RuntimeException(e);}return pdfOutputStream;}/*** pdfBytes转图片Base64单个字节流处理** param pdfBytes* param watermarkText* return*/private ListString pdfByteToImageBase64Single(byte[] pdfBytes, String watermarkText) {ListString imageBase64List new ArrayList();try (PDDocument document PDDocument.load(pdfBytes)) {PDFRenderer pdfRenderer new PDFRenderer(document);for (int pageIndex 0; pageIndex document.getNumberOfPages(); pageIndex) {BufferedImage image pdfRenderer.renderImageWithDPI(pageIndex, 300, ImageType.RGB);ByteArrayOutputStream baos new ByteArrayOutputStream();ImageIO.write(image, png, baos);baos.flush();byte[] imageBytes baos.toByteArray();baos.close();if (StringUtils.isNotBlank(watermarkText)) {try (InputStream watermarkedInputStream addImageWaterMark(new ByteArrayInputStream(imageBytes), watermarkText)) {byte[] watermarkedBytes watermarkedInputStream.readAllBytes();watermarkedInputStream.close();String format png;String fullEncodedImage data:image/ format ;base64, Base64.getEncoder().encodeToString(watermarkedBytes);imageBase64List.add(fullEncodedImage);} catch (IOException e) {logger.error(添加水印时发生错误, e);}} else {String format png;String fullEncodedImage data:image/ format ;base64, Base64.getEncoder().encodeToString(imageBytes);imageBase64List.add(fullEncodedImage);}}} catch (IOException e) {logger.error(处理PDF字节流时发生错误, e);}return imageBase64List;}/*** pdf转图片Base64** param pdfFilePathList* param watermarkText* return*/public ListString pdfFileToImageBase64(ListString pdfFilePathList, String watermarkText) {ListString imageBase64List new ArrayList();ExecutorService executor Executors.newFixedThreadPool(MAX_CONCURRENT_TASKS);try {// 提交任务到线程池ListFutureListString futures new ArrayList();for (String filePath : pdfFilePathList) {CallableListString task () - convertSinglePdfToImageBase64(filePath, watermarkText);futures.add(executor.submit(task));}// 收集所有任务的结果for (FutureListString future : futures) {try {// 获取并合并每个任务的结果imageBase64List.addAll(future.get());} catch (InterruptedException | ExecutionException e) {Thread.currentThread().interrupt();logger.error(处理PDF文件时发生错误, e);}}} finally {executor.shutdown();try {if (! executor.awaitTermination(60, TimeUnit.SECONDS)) {executor.shutdownNow();}} catch (InterruptedException e) {executor.shutdownNow();Thread.currentThread().interrupt();logger.error(关闭线程池时发生中断, e);}}return imageBase64List;}/*** 单个PDF转图片Base64** param filePath* param watermarkText* return*/private ListString convertSinglePdfToImageBase64(String filePath, String watermarkText) {ListString singleFileImageBase64List new ArrayList();try (PDDocument document PDDocument.load(new FileSystemResource(filePath).getFile())) {PDFRenderer pdfRenderer new PDFRenderer(document);for (int pageIndex 0; pageIndex document.getNumberOfPages(); pageIndex) {BufferedImage image pdfRenderer.renderImageWithDPI(pageIndex, 300, ImageType.RGB);ByteArrayOutputStream baos new ByteArrayOutputStream();ImageIO.write(image, png, baos);baos.flush();byte[] imageBytes baos.toByteArray();baos.close();if (StringUtils.isNotBlank(watermarkText)) {try (InputStream watermarkedInputStream addImageWaterMark(new ByteArrayInputStream(imageBytes), watermarkText)) {byte[] watermarkedBytes watermarkedInputStream.readAllBytes();String format png;String fullEncodedImage data:image/ format ;base64, Base64.getEncoder().encodeToString(watermarkedBytes);singleFileImageBase64List.add(fullEncodedImage);} catch (IOException e) {logger.error(添加水印时发生错误, e);}} else {String format png;String fullEncodedImage data:image/ format ;base64, Base64.getEncoder().encodeToString(imageBytes);singleFileImageBase64List.add(fullEncodedImage);}}} catch (IOException e) {logger.error(加载PDF文档时发生错误, e);}return singleFileImageBase64List;}/*** 图片转为base64编码** param imageFilePathList* param watermarkText* return*/public ListString imageFileToBase64(ListString imageFilePathList, String watermarkText) {ListString imageBase64List new ArrayList();ExecutorService executor Executors.newFixedThreadPool(MAX_CONCURRENT_TASKS);try {// 提交任务到线程池ListFutureString futures imageFilePathList.stream().map(path - executor.submit(() - convertSingleImageToBase64(path, watermarkText))).collect(Collectors.toList());// 收集所有任务的结果for (FutureString future : futures) {try {// 添加每个任务返回的Base64编码字符串imageBase64List.add(future.get());} catch (InterruptedException | ExecutionException e) {Thread.currentThread().interrupt();logger.error(处理图像文件时发生错误, e);}}} finally {executor.shutdown();try {if (! executor.awaitTermination(60, TimeUnit.SECONDS)) {executor.shutdownNow();}} catch (InterruptedException e) {executor.shutdownNow();Thread.currentThread().interrupt();logger.error(关闭线程池时发生中断, e);}}return imageBase64List;}/*** 单个图像文件转换为Base64字符串** param imagePath 图像文件路径* param watermarkText* return Base64编码的字符串*/private String convertSingleImageToBase64(String imagePath, String watermarkText) {try {File file new File(imagePath);InputStream originalInputStream new FileInputStream(file);if (StringUtils.isNotBlank(watermarkText)) {try (InputStream watermarkedInputStream addImageWaterMark(originalInputStream, watermarkText)) {byte[] bytes watermarkedInputStream.readAllBytes();String format getFileExtension(file.getName()).toLowerCase();String fullEncodedImage data:image/ format ;base64, Base64.getEncoder().encodeToString(bytes);return fullEncodedImage;}} else {String format getFileExtension(file.getName()).toLowerCase();String fullEncodedImage data:image/ format ;base64, Base64.getEncoder().encodeToString(originalInputStream.readAllBytes());return fullEncodedImage;}} catch (Exception e) {logger.error(转换图像文件为Base64时出错: imagePath, e);return null;}}/*** 获取文件扩展名** param fileName* return*/private static String getFileExtension(String fileName) {int lastIndexOfDot fileName.lastIndexOf(.);if (lastIndexOfDot - 1) {// 没有找到扩展名的情况return ;}return fileName.substring(lastIndexOfDot 1);}/*** 判断word是doc还是docx** param file* return*/public String getFileType(File file) {String fileName file.getName();int dotIndex fileName.lastIndexOf(.);if (dotIndex 0 dotIndex fileName.length() - 1) {String extension fileName.substring(dotIndex 1).toLowerCase();if (docx.equals(extension)) {return docx;} else if (doc.equals(extension)) {return doc;}}return null;}/*** 给照片添加水印** param inputStream* param waterMarkText* return*/public InputStream addImageWaterMark(InputStream inputStream, String waterMarkText) throws IOException {if (waterMarkText null || waterMarkText ) {return inputStream;}BufferedImage image;try {image ImageIO.read(inputStream);} catch (IOException e) {throw e;}int width image.getWidth();int height image.getHeight();BufferedImage watermarkedImage new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);Graphics2D g2d watermarkedImage.createGraphics();// 绘制原始图像到新图像g2d.drawImage(image, 0, 0, width, height, null);// 设置抗锯齿g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);// 设置水印的字体和颜色包括透明度Font font new Font(STSong-Light, Font.BOLD, 30); // 可以调整字体大小g2d.setFont(font);g2d.setColor(new Color(0, 0, 0, 255)); // 红色透明度为 25%g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 0.2f));// 创建旋转变换AffineTransform originalTransform g2d.getTransform();AffineTransform rotateTransform new AffineTransform();rotateTransform.rotate(Math.toRadians(- 30), 0, 0);g2d.setTransform(rotateTransform);// 获取字体度量信息FontMetrics fontMetrics g2d.getFontMetrics();int watermarkWidth fontMetrics.stringWidth(waterMarkText);int watermarkHeight fontMetrics.getHeight();// 将图像用水印铺满for (int x - width; x width * 2; x watermarkWidth 100) {for (int y - height; y height * 2; y watermarkHeight 100) {g2d.drawString(waterMarkText, x, y);}}// 恢复原始变换g2d.setTransform(originalTransform);g2d.dispose();// 将带有水印的图像写入ByteArrayOutputStreamByteArrayOutputStream os new ByteArrayOutputStream();try (ImageOutputStream ios ImageIO.createImageOutputStream(os)) {if (! ImageIO.write(watermarkedImage, jpg, ios)) {throw new IOException(Failed to write watermarked image to output stream);}} catch (IOException e) {throw e;} finally {try {os.close();} catch (IOException e) {throw e;}}// 返回处理后的图像流return new ByteArrayInputStream(os.toByteArray());}/*** 给PDF添加水印** param inputStream* param waterMarkText* return*/public InputStream addPdfWaterMark(InputStream inputStream, String waterMarkText) {if (waterMarkText null || waterMarkText ) {return inputStream;}OutputStream outputStream null;PdfReader pdfReader null;PdfStamper pdfStamper null;try {// 水印的高和宽int waterMarkHeight 30;int watermarkWeight 60;// 水印间隔距离int waterMarkInterval 100;outputStream new ByteArrayOutputStream();// 读取PDF文件流pdfReader new PdfReader(inputStream);// 创建PDF文件的模板可以对模板的内容修改重新生成新PDF文件pdfStamper new PdfStamper(pdfReader, outputStream);// 设置水印字体BaseFont baseFont BaseFont.createFont(STSong-Light, UniGB-UCS2-H, BaseFont.EMBEDDED);// 设置PDF内容的Graphic State 图形状态PdfGState pdfGraPhicState new PdfGState();// 填充透明度pdfGraPhicState.setFillOpacity(0.2f);// 轮廓不透明度pdfGraPhicState.setStrokeOpacity(0.4f);// PDF页数int pdfPageNum pdfReader.getNumberOfPages() 1;// PDF文件内容字节PdfContentByte pdfContent;// PDF页面矩形区域com.itextpdf.text.Rectangle pageRectangle;for (int i 1; i pdfPageNum; i) {// 获取当前页面矩形区域pageRectangle pdfReader.getPageSizeWithRotation(i);// 获取当前页内容getOverContent表示之后会在页面内容的上方加水印pdfContent pdfStamper.getOverContent(i);// 获取当前页内容getOverContent表示之后会在页面内容的下方加水印// pdfContent pdfStamper.getUnderContent(i);pdfContent.saveState();// 设置水印透明度pdfContent.setGState(pdfGraPhicState);// 开启写入文本pdfContent.beginText();// 设置字体pdfContent.setFontAndSize(baseFont, 15);// 在高度和宽度维度每隔waterMarkInterval距离添加一个水印for (int height waterMarkHeight; height pageRectangle.getHeight(); height height waterMarkInterval) {for (int width watermarkWeight; width pageRectangle.getWidth() watermarkWeight;width width waterMarkInterval) {// 添加水印文字并旋转30度角pdfContent.showTextAligned(Element.ALIGN_LEFT, waterMarkText, width - watermarkWeight,height - waterMarkHeight, 30);}}// 停止写入文本pdfContent.endText();}pdfStamper.close();pdfReader.close();} catch (Exception e) {e.printStackTrace();} finally {try {if (pdfReader ! null) {pdfReader.close();}if (inputStream ! null) {inputStream.close();}if (outputStream ! null) {outputStream.flush();outputStream.close();}} catch (IOException e) {throw new RuntimeException(e);}}return new ByteArrayInputStream(((ByteArrayOutputStream) outputStream).toByteArray());}/*** 给word添加水印** param inputStream* param waterMarkText* return*/public InputStream addWordWaterMark(InputStream inputStream, String waterMarkText) {if (waterMarkText null || waterMarkText ) {return inputStream;}try {XWPFDocument doc new XWPFDocument(inputStream);WordWaterMarker.makeFullWaterMarkByWordArt(doc, waterMarkText, #d8d8d8, 0.5pt, -30);ByteArrayOutputStream os new ByteArrayOutputStream();doc.write(os);return new ByteArrayInputStream(os.toByteArray());} catch (IOException e) {e.printStackTrace();}return null;} }2.5model层代码 DownloadFile.java完整代码如下 package com.example.testdemo.test.model;import lombok.Data; import java.util.List;/*** 项目名称: testDemo* 作者: zhaojs* 创建日期: 2024年07月04日* 文件说明: 见类描述*/ Data public class DownloadFile {/*** 附件id多个用,隔开*/private String attachmentIds;/*** 文件压缩包名*/private String fileZipName;/*** 水印文字*/private String watermarkText; }Attachment.java完整代码如下 package com.example.testdemo.test.model;import java.time.LocalDateTime; import java.util.Date; import java.io.Serializable;import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data;/*** 附件表实体类* author zhaojs* date 2024-07-04*/ Data TableName(ATTACHMENT) public class Attachment implements Serializable {/*** 序列化变量*/private static final long serialVersionUID 697303854047803428L;/*** 主键id*/TableIdprivate String attachmentId;/*** 文件id*/private String fileId;/*** 文件名*/private String fileName;/*** 文件类型*/private String fileType;/*** 文件大小*/private Double fileSize;/*** 文件路径*/private String filePath;/*** 创建人id*/private String createUserId;/*** 创建人姓名*/private Integer createUserName;/*** 创建时间*/private LocalDateTime createTime;/*** 更新人id*/private String updateUserId;/*** 更新人姓名*/private String updateUserName;/*** 更新时间*/private LocalDateTime updateTime;/*** 文件过期时间*/private LocalDateTime expireTime; }2.6dao层代码 AttachmentDao.java完整代码如下对应的mapper文件自己映射就好这里就不给出了 package com.example.testdemo.test.dao;import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.example.testdemo.test.model.Attachment; import org.apache.ibatis.annotations.Mapper; import org.springframework.stereotype.Repository;/*** 附件表Dao接口* author zhaojs* date 2024-07-04*/ public interface AttachmentDao extends BaseMapperAttachment { }2.6说明 1代码内的数据库表自己创建参考Attachment.java即可。 2到此就可以使用了Linux和Windows都可以启动项目前记得把libreoffice也启起来也就是1.3启动libreoffice。 3若是转换过程发现报错Cause: java.sql.SQLException: Incorrect string value: ‘?μ?èˉ?..’ for column ‘FILE_NAME’ at row 1 ; uncategorized SQLException; SQL state [HY000]; error code [1366]; Incorrect string value: ‘?μ?èˉ?..’ for column ‘FILE_NAME’ at row 1; nested exception is java.sql.SQLException: Incorrect string value: ‘?μ?èˉ?..’ for column ‘FILE_NAME’ at row 1] with root cause 则是字符集编码引起的执行下面命令修改mysql字符集即可 ALTER TABLE 表名 CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;ALTER DATABASE 数据库名 CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
http://www.sczhlp.com/news/228783/

相关文章:

  • 出版社网站建设代理平台软件
  • 毕业设计 建设旅游网站腾讯云wordpress教程视频
  • 绵阳辉煌网站建设怎么在手机上搭建网站
  • 万网 手机网站安丘做网站
  • 纯前端网站怎么做rest网站建设维护需要懂哪些知识
  • 做PPT素材图片网站 知乎wordpress修订管理
  • wordpress网站好用吗网站优化怎么做
  • 做英语在线翻译兼职网站绿色网站风格
  • 怎么查看网站是否被百度惩罚降权或者被kwordpress 单本
  • 近期时政热点新闻20条杭州优化建筑设计
  • 27WordPress主题做企业网站模板可以seo
  • 企业网站营销如何建设在线免费网站
  • 起名网站开发凉山州建设厅官方网站
  • 网站做百科建设银行网站 开户行怎么查
  • 内部网站建设专业网站建设哪家好
  • 南宁网站建设liluokjwordpress xml文件分割器
  • ae模板免费网站建设网站的实验目的和意义
  • 测试文档
  • 【华为云 ToB 大模型团队】校园招聘
  • wordpress 修改站点石家庄红酒公司 网站建设
  • 好的排版设计网站哪个企业的网站做的比较好
  • 常宁网站制作建设银行网站官网
  • 石河子做网站公司海口关键词优化报价
  • 中国空间站图片绘画wordpress cron
  • 一屏一屏的网站怎么做建设工程公司名称大全
  • 学做网站 为了熊掌号免费看网站源码
  • 做编程的 网站有哪些做外汇消息面的网站
  • 邢台市网站制作 网站建设.net做网站开发吗
  • 背景网站建设wordpress 精致主题
  • 盗版视频网站建设费用北京注册公司虚拟地址