很多曾经攻克过的难题都没有及时记录并分享,觉得有些可惜。趁着现在还单身,头还没秃,精力也还算旺盛,我便整理出一些自己曾经挑灯夜战、独立实现的还算有些成就感的项目需求,记录在个人博客上,希望能给拥有相同需求的同行提供一些参考。下面要说的这个需求,真的实现后,会发现其实并没有太多技术含量,分开来讲,也就两个步骤:(1)文件上传;(2)PDF转JPG。文件上传插件的使用没有太大的要求,只要能实现上传图片的功能就可以,关键是PDF转JPG的代码实现,博客上能找到很多相关的帖子,但并非都好用,下面分享的,是我亲测之后可以满足我项目需求的。

先说需求:由于网站的某个流程中,需要角色A的用户上传一个可能是JPG格式也可能是PDF格式的文件,然后希望角色B的用户可以在PC端、APP端和微信公众号端都能实时查看下载这个文件到自己的设备上,并且要求这个文件在A4 纸上打印后的效果和原文件一样,能保证正常的使用。我的解决方案如下:

(1)首先对角色A的用户能够上传的文件格式进行前端限制,只允许上传JPG和PDF格式的文件(由于本身项目的特殊性,所以能够保证用户上传的该类文件一定是这两种格式中的一种)。

(2)对角色A的用户上传到服务器的文件进行后端校验并处理:  ①如果是图片格式(JPG/PNG)的文件,就直接保存,并把保存后的图片路径返回给前端。  ②如果是PDF格式的文件,仍旧保存这个文件,然后得到这个PDF文件在我们服务器的硬盘上的路径,然后调用PDF转JPG的工具类进行转换,如果转换成功,返回转成功的图片的文件路径;如果失败,则返回给前端错误提示,要求传入正确的文件,因为能够确定,标准的文件是一定能够转换成成功的。③如果用户上传的文件不是这两种格式的(虽然前端做了校验,但难免有恶意请求进来的情况,所以永远不要过度相信前端传来的数据,尤其是涉及到敏感操作的时候),则不保存文件,程序结束并返回错误提示。

上传图片的插件有很多,我是使用FileUpload实现Servlet的文件上传,可参考这篇博客 https://blog.csdn.net/llkoio/article/details/78984466 来使用,此处就不花篇幅赘述。

下面直接上代码!!!

package fileupload;import java.io.File;
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;import com.alibaba.fastjson.JSON;import DateUtil;import PdfToPngUtils;/*** * @ClassName: PlUploadServlet* @Description: TODO(这里用一句话描述这个类的作用)* @author hqq**/
public class PlUploadServlet extends HttpServlet {/*** */private static final long serialVersionUID = 1L;private static final Logger logger = Logger.getLogger(PlUploadServlet.class);public PlUploadServlet() {super();}@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {doPost(request, response);}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {response.setCharacterEncoding("UTF-8");//业务代码隐身符,此处省略判断用户权限的代码,每个人的权限控制都不同,故省略String orderId = "";// 订单号String type = "";// 类型String userId = "";// 用户idString carId = "";// String folder = "";// 文件夹String webParentPath = "";// 文件上传到服务器的真实路径,不包含文件名String retrunPath = "";// 返回给前端的绝对路径String myName = "";// 保存到服务的文件命名String fileName = "";// 是否有系统定义的文件名传来boolean pdf2jpg = false;// 是否需要pdf转jpgString dateFolder = DateUtil.dateToString(new Date(), "yyyy-MM-dd");String basePath = "D:/tom/webapps/myProject/file";//硬盘的实际目录String baseReturn = "/file";Map<String, Object> m = new HashMap<String, Object>();if (ServletFileUpload.isMultipartContent(request)) {try {DiskFileItemFactory factory = new DiskFileItemFactory();// 设置工厂的内存缓冲区大小,默认是1Mfactory.setSizeThreshold(1024 * 1024);// 设置工厂的临时文件目录:当上传文件的大小大于缓冲区大小时,将使用临时文件目录缓存上传的文件factory.setRepository(new File("D:/Tomcat/webapps/struck2.0/temp"));// 文件上传解析器ServletFileUpload upload = new ServletFileUpload(factory);// 设置所有上传数据的最大值,单位字节long 5Mupload.setSizeMax(1024 * 1024 * 5);// 设置单个文件上传的最大值upload.setFileSizeMax(1024 * 1024 * 5);// 设置编码格式upload.setHeaderEncoding("UTF-8");// 解析请求,将表单中每个输入项封装成一个FileItem对象List<FileItem> items = upload.parseRequest(request);for (FileItem item : items) {if (item.isFormField()) { // 是文本域switch (item.getFieldName()) {case "userId":// 获取到的userIduserId = item.getString();break;case "orderId":orderId = item.getString();break;case "carId":carId = item.getString();case "type":type = item.getString();logger.info("本次上传的文件类型是:" + type);break;case "fileName":// 有文件名过来fileName = new String(item.getString().getBytes("ISO-8859-1"), "utf-8");// 中文转码logger.info("客户端传了文件名,不需要服务端重新命名。传来的名字是:" + fileName);break;}} else {// 如果是文件类型// 没有传入userId是不允许的哦if (StringUtils.isBlank(userId)) {m.put("status", false);m.put("fileUrl", "缺少必要的参数,您无法上传");response.getWriter().write(JSON.toJSONString(m));return;}// 判断文件类型String suffix = FileType.getSuffix(item.getContentType());if (suffix == null) {m.put("status", false);m.put("fileUrl", "暂不支持该类型的文件上传");response.getWriter().write(JSON.toJSONString(m));return;}// 定义文件名myName = UUID.randomUUID().toString().replaceAll("-", "");//我主张将不同类型的文件放在不同的文件夹中,因为调用接口的时候,我们就知道要上传的是哪种业务的文件了,这样便于后期管理switch (type.toUpperCase()) {case "AFILE"://A类文件pdf2jpg = true;//我项目规定该类型上传时可以是pdf和jpg,但是最终保存后必须是jpg格式的folder = "/order/sofile/" + dateFolder + "/" + userId + "/";break;case "BPIC":// B类图片folder = "/order/" + dateFolder + "/" + orderId + "/";myName = type + "_" + orderId + "_" + carId + "_" + System.currentTimeMillis();break;case "USERINFO":// 其它文件folder = "/user/" + userId + "/";if (StringUtils.isBlank(fileName)) {myName = "USERIMAGE_" + myName + "_" + System.currentTimeMillis();} else {myName = fileName;}break;case "ORDEREXCEL":// 其它文件folder = "/excel/" + userId + "/" + dateFolder + "/";break;default:folder = "/unknown/" + dateFolder + "/";break;}myName = myName + suffix;// 判断是否是pdf文件并且最终是否需要转换成jpg文件if (pdf2jpg && suffix.equals(".pdf")) {pdf2jpg = true;} else {pdf2jpg = false;}// 设置图片路径webParentPath = basePath + folder;// 文件上传到服务器的真实路径,不包含文件名retrunPath = baseReturn + folder;// 返回给前端的绝对路径File up = new File(webParentPath);if (!up.exists()) {up.mkdirs();}File savedFile = new File(webParentPath, myName);item.write(savedFile);}}m.put("status", true);m.put("fileUrl", retrunPath + myName);// 将pdf文件转成jpgif (pdf2jpg) {myName = PdfToPngUtils.pdfToImage(webParentPath + myName, myName);if (myName != null) {m.put("status", true);m.put("fileUrl", retrunPath + myName);} else {m.put("status", false);m.put("fileUrl", "pdf转换图片失败,请确定传入的是提还柜单,或者传入图片格式的提还柜单");}}} catch (Exception e) {logger.info("网络异常:" + e.getMessage());m.put("status", false);m.put("fileUrl", "网络异常:" + e.getMessage());}} else {m.put("status", false);m.put("fileUrl", "您传入的不是文件");}response.getWriter().write(JSON.toJSONString(m));}}

更加详细的PlUploadServlet.java类,请参照我的上一篇博客https://blog.csdn.net/weixin_42023666/article/details/89461198。现在看到的这个PlUploadServlet.java工具类便是从这里改编过来的,此处不做赘述。下面直接上核心的pdf转jpg工具类PdfToPngUtils.java类:

package fileupload;import java.awt.image.BufferedImage;
import java.io.File;import javax.imageio.ImageIO;import org.apache.commons.lang3.StringUtils;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.ImageType;
import org.apache.pdfbox.rendering.PDFRenderer;/*** @ClassName: PdfToPngUtils* @Description: TODO(这里用一句话描述这个类的作用)* @author hqq*/
public class PdfToPngUtils {// 经过测试,dpi为96,100,105,120,150,200中,105显示效果较为清晰,体积稳定,dpi越高图片体积越大。一般电脑显示分辨率为96public static final Integer DEFAULT_DPI = 200;// 此处dpi设置成200,因为我的项目需求要求转换成的图片最终需要在A4纸打印出来并使用。可以根据各自实际需求修改此值,还可以将此值设置成变量,由调用者决定清晰度/*** pdf文件转换成jpg图片,亲测只要是一张图片的pdf原文件,百分之百能转换成功* @param pdfPath 要转换的pdf文件的绝对路径* @param fileName 要转换的pdf文件的文件名,带后缀* @return 返回转换成功后的文件名,带后缀;注意此时转换出的图片与pdf原文件在同级目录*/public static String pdfToImage(String pdfPath,String fileName) {String jpgName=null;try {if (StringUtils.isBlank(pdfPath) || !pdfPath.toLowerCase().endsWith(".pdf")) {System.out.println("pdf转JPG,传入的pdf图片路径为空或传入的不是pdf文件");return null;}if(StringUtils.isBlank(fileName)||!fileName.toLowerCase().endsWith(".pdf")){System.out.println("pdf转jpg失败,传入的文件名为空或者传入的不是pdf文件");return null;}// 图像合并使用参数int width = 0; // 总宽度int[] singleImgRGB; // 保存一张图片中的RGB数据int shiftHeight = 0;BufferedImage imageResult = null;// 保存每张图片的像素值// 利用PdfBox生成图像PDDocument pdDocument = PDDocument.load(new File(pdfPath));PDFRenderer renderer = new PDFRenderer(pdDocument);// 循环每个页码for (int i = 0, len = pdDocument.getNumberOfPages(); i < len; i++) {BufferedImage image = renderer.renderImageWithDPI(i, DEFAULT_DPI, ImageType.RGB);int imageHeight = image.getHeight();int imageWidth = image.getWidth();if (i == 0) {// 计算高度和偏移量width = imageWidth;// 使用第一张图片宽度;// 保存每页图片的像素值imageResult = new BufferedImage(width, imageHeight * len, BufferedImage.TYPE_INT_RGB);} else {shiftHeight += imageHeight; // 计算偏移高度}singleImgRGB = image.getRGB(0, 0, width, imageHeight, null, 0, width);imageResult.setRGB(0, shiftHeight, width, imageHeight, singleImgRGB, 0, width); // 写入流中}pdDocument.close();jpgName=pdfPath.replace(".pdf", "_" + DEFAULT_DPI + ".jpg");File outFile = new File(jpgName);//新的文件名jpgName=fileName.replace(".pdf", "_" + DEFAULT_DPI + ".jpg");ImageIO.write(imageResult, "jpg", outFile);// 写图片System.out.println("PDF转JPG成功");} catch (Exception e) {jpgName=null;System.out.println("PDF转JPG失败:"+e.getMessage());}return jpgName;}}

依赖的jar文件,好像只要第二个就可以,安全起见还是两个都弄上,也可以直接传jar包,同样的去maven仓库直接下载对应的jar,不过需要留意将他们依赖的其它jar包一起引入:

     <!-- pdf转图片 --><dependency><groupId>org.apache.pdfbox</groupId><artifactId>fontbox</artifactId><version>2.0.9</version></dependency><!-- https://mvnrepository.com/artifact/org.apache.pdfbox/pdfbox --><dependency><groupId>org.apache.pdfbox</groupId><artifactId>pdfbox</artifactId><version>2.0.9</version></dependency>

至此,功能实现,留个纪念。

JAVA如何实现将用户上传的PDF文件转换成图片并返回给用户相关推荐

  1. 不支持所上传的文件格式。请确认选择的文件无误。_职场人必备!如何把PDF文件转换成word文档?...

    点击箭头处"蓝色字",关注我们哦!! 再撑一下!明天就是周末了! PDF大家都用过,它是平时我们办公中最常用到的文件格式之一.它是一种可移植文档格式,与操作系统平台无关,在任何系统 ...

  2. 文件上传至将File转换成MultiPartFile

    在文件上传业务上需要将文件上传至将File转换成MultiPartFile的时候,我搜索得到采用MockMultipartFile这个类可以轻松的转换. 但是,当我准备使用的时候,坑出现了.它是spr ...

  3. ASP.Net中实现上传过程中将文本文件转换成PDF的方法

    iTextSharp是一个常用的PDF库,我们可以使用它来创建.修改PDF文件或对PDF文件进行一些其他额外的操作.本文讲述了如何在上传过程中将文本文件转换成PDF的方法. 基本工作 在开始之前,我们 ...

  4. C# 上传WPS Excel 后台转换成txt,再压缩为ZIP

    一开始在读取ET文件的时候用的是etapi.dll自带插件,发现调试时会报各种各样的拒绝访问的错误,创建txt文件报[对路径"c:\\windows\\system32\\inetsrv\\ ...

  5. vue-tinymce的使用,粘贴文件上传,自定义文件上传,改base64转换成上传到服务器返回url

    vue-tinymce的使用,粘贴文件上传,自定义文件上传,改base64转换成上传到服务器返回url vue中使用 <vue-tinymcev-model="itemForm.con ...

  6. Java使用aspose把PDF文件转换成PNG文件,以及把PDF文件水印转换成PNG格式

    Java代码把PDF文件转换成PNG文件 需要引用aspose包,引入操作我写了一个博客,地址如下 https://blog.csdn.net/weixin_46713508/article/deta ...

  7. 转jpg java源程序_将pdf文件转成图片并删除java源代码

    将pdf文件转成图片并删除java源代码/** * 将pdf转成img */ public static void changePdfToImg() { try { File file = new F ...

  8. 上传绕过php文件改为图片,文件上传漏洞另类绕过技巧及挖掘案例全汇总

    文件上传漏洞作为获取服务器权限最快的方式,虽然相关资料很多,但很多人对上传校验方式.如何针对性绕过检测.哪种上传和解析的场景会产生危害等还是比较模糊.本文作一些阐述,然后补充一些除了上传webshel ...

  9. PPTPDF文件转换成图片上传OSS

    PPTPDFIMAGE 先把文件上传至本地,再去读取文件转变上传. <dependency><groupId>org.apache.pdfbox</groupId> ...

最新文章

  1. 机器学习与高维信息检索 - Note 4 - 主成分分析及其现代解释(Principal Component Analysis, PCA)及相关实例
  2. ICCV2021 Oral SimROD:简单高效的数据增强!华为提出了一种简单的鲁棒目标检测自适应方法...
  3. 最小熵原理系列:词向量的维度应该怎么选择?
  4. 面向对象编程02—装饰器、类方法、静态方、访问控制
  5. [转载]-如何向妻子解释OOD
  6. 本地项目如何连接码云上的项目
  7. vcpkg安装_微软牌包管理器vcpkg更新及路线图计划
  8. mysql数据库备份shell_mysql数据库备份shell脚本分享
  9. Android strings.xml中定义字符串显示空格
  10. DreamFactory 第7章 限制和记录API请求
  11. python电脑下载-python
  12. BZOJ 1599: [Usaco2008 Oct]笨重的石子( 枚举 )
  13. 深度学习TF—7.卷积神经网络CNN
  14. openstack错误汇总
  15. Oracle创建用户、授权、规则
  16. python下载网易云音乐中某个歌单中的全部音乐
  17. 主成分分析结果成分不显著_主成分分析结果
  18. 南澳大学计算机科学专业学费,2020年南澳大学学费(本科及研究生)及学费支付方式解析!...
  19. 基于复化辛卜生求积公式的变步长求积算法
  20. python如何调用pyd_C#调用pyd

热门文章

  1. Orange下载与安装
  2. 魅族mx4pro刷linux,刷机大师:完美支持魅族MX4 Pro一键刷机及ROOT
  3. ORA-04021:等待锁定对象时发生超时
  4. 在MTU为1500,不分片的条件下,ping包长最大为1472B的理解
  5. codesoft6卸载干净_CODESOFT创建和删除自定义文档备料
  6. 学计算机要买什么游戏本,学设计的应该买什么配置的笔记本电脑才好呢?
  7. CYDIA闪退解决办法
  8. 汇编实验(扬声器程序设计)
  9. 模拟测试20190806
  10. 使用老毛桃u盘启动盘制作工具安装Win7图文教程