Office文档上传后实时转换为PDF格式_图片文件上传后实时裁剪_实现在线预览Office文档

Office文档上传后实时转换为PDF格式_图片文件上传后实时裁剪

 

前置条件

  • 安装LibreOffice
  • 安装OpenOffice
  • 安装Unoconv
  • 安装ImageMagick.x86_64
  • 安装GraphicsMagick.x86_64

 

思路说明

office文档上传后,执行Shell脚本命令,转换文档

libreoffice命令:

//如果是Word文档,则转化为PDF ,如果是Excel,则转换为html(将pdf:writer_pdf_Export替换为html) ,{src}替换为待转换文档全路径+名称,{des}替换为转换后存放路径
command = "libreoffice --convert-to pdf:writer_pdf_Export {src} --outdir {des}";

openoffice命令:

//如果是Word文档,则转化为PDF ,如果是Excel,则转换为html(将pdf:writer_pdf_Export替换为html) ,{src}替换为待转换文档全路径+名称,{des}替换为转换后存放路径
command = "soffice --headless --invisible --convert-to pdf:writer_pdf_Export {src} --outdir {des} "

unoconv命令:

//老版本的Word可能转换异常,使用unoconv转换;{src}替换为待转换文档全路径+名称,{des}替换为转换后存放路径
command = "unoconv -f pdf {src} -o {des} ";

图片文档上传后,执行Shell脚本命令,压缩或裁剪图片

//裁剪图片目录,注意{src}原图片路径+命令 {des}目标图片路径+命令
command = "convert {src} -resize 240x160 {des} "

执行命令如下:

//Java执行操作系统Shell命令
Runtime.getRuntime().exec(command);

 

异常解决

注意是中文转化乱码的问题

解决思路一:安装中文包

//搜索libreoffice的中文包,如果有,安装即可
yum search libreoffice

//搜索openoffice的中文包,如果有,安装即可
yum search openoffice

//搜索unoconv的中文版,如果有,安装即可
yum search unoconv

举例:libreoffice的中文包,简体、繁体一并安装了,免得有些文档有繁体,转换后乱码

libreoffice-langpack-zh-Hans.x86_64 : Simplified Chinese language pack for LibreOffice
libreoffice-langpack-zh-Hant.x86_64 : Traditional Chinese language pack for LibreOffice

解决思路二:复制Windows上的字体包到Linux系统上并安装

具体方法:https://blog.csdn.net/Aria_Miazzy/article/details/103830850

 

转换代码

package org.jeecg.common.system.controller;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.jeecg.common.api.vo.Result;
import org.jeecg.common.util.BashUtil;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.servlet.HandlerMapping;
import org.springframework.web.servlet.ModelAndView;

import lombok.extern.slf4j.Slf4j;

/**
 * <p>
 * 用户表 前端控制器
 * </p>
 *
 * @Author scott
 * @since 2018-12-20
 */
@Slf4j
@RestController
@RequestMapping("/sys/common")
public class CommonController {

	@Value(value = "${jeecg.path.upload}")
	private String uploadpath = "/root/jeecg/upFiles";

	@Value(value = "${jeecg.path.convert}")
	private String convert = "convert";

	/**
	 * @Author 政辉
	 * @return
	 */
	@GetMapping("/403")
	public Result<?> noauth()  {
		return Result.error("没有权限,请联系管理员授权");
	}

	/**
	 * @function 上传函数
	 * @param request
	 * @param response
	 * @return
	 */
	@PostMapping(value = "/upload")
	public Result<?> upload(HttpServletRequest request, HttpServletResponse response) {

		//定义返回结果
		Result<?> result = new Result<>();

		//定义上传区域块
		try {

			//获取上传目录
			String ctxPath = uploadpath;
			//定义文件名称
			String fileName = null;
			//定义图片名称
			String thumborName = null;
            //设置图片名称
            String thumborName100x60 =null;
            //定义图片名称
            String originName = null;
            //定义上传文件子目录
			String bizPath = "files";
			//获取当前时间
			String nowtime = new SimpleDateFormat("yyyyMMddhhmmssSSS").format(new Date());
			//获取文件上传目录
			File file = new File(ctxPath + File.separator + bizPath);

			//如果文件不存在,则创建文件根目录
			if (!file.exists()) {
				file.mkdirs();
			}

			//获取多媒体Request请求对象
			MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;

			// 获取上传文件对象
			MultipartFile mf = multipartRequest.getFile("file");

			//获取文件名
			String orgName = mf.getOriginalFilename();
			//获取文件类型
			String fileType = orgName.substring(orgName.indexOf(".")).toLowerCase();

			//重命名文件
			fileName = nowtime + "_" + orgName.substring(0, orgName.lastIndexOf(".")).replaceAll(" ","")  + fileType;

			//设置图片名称
			thumborName = nowtime  + "_" + orgName.substring(0, orgName.lastIndexOf(".")).replaceAll(" ","") + "_S240x160" + fileType;

            //设置图片名称
            thumborName100x60 = nowtime  + "_" + orgName.substring(0, orgName.lastIndexOf(".")).replaceAll(" ","") + "_S100x60" + fileType;

            //设置图片名称
            originName = nowtime  + "_" + orgName.substring(0, orgName.lastIndexOf(".")).replaceAll(" ","") + fileType;

			//设置保存路径
			String savePath = file.getPath() + File.separator + fileName;

			//设置可以执行保存的文件对象
			File savefile = new File(savePath);

			//执行保存文件操作
			FileCopyUtils.copy(mf.getBytes(), savefile);

			//设置应显示的文件保存路径
			String dbpath = bizPath + File.separator + fileName;

			//字符串\\转换为/
			if (dbpath.contains("\\")) {
				dbpath = dbpath.replace("\\", "/");
			}

			//定义待执行命令
			String command = null;

			//如果是Excel文档,则转化为Html,如果是Word文档,则转化为PDF文档,如果是PPT文档,则转化为PDF文档,如果是图片,则进行压缩处理
			if(fileType.equals(".xlsx") || fileType.equals(".xls")) {
				//如果是Excel文档,则转化为Html
				command = "libreoffice --convert-to html {src} --outdir {des}";
			} else if(fileType.equals(".doc")) {
				//老版本的Word可能转换异常,使用unoconv转换
				command = "unoconv -f pdf {src} -o {des} ";
			} else if(fileType.equals(".ppt")) {
				//老版本的Word可能转换异常,使用unoconv转换
				command = "unoconv -f pdf {src} -o {des} ";
			} else if(fileType.equals(".docx")){
			    //如果是Word文档,则转化为PDF
				command = "libreoffice --convert-to pdf:writer_pdf_Export {src} --outdir {des}";
			} else if(fileType.equals(".pptx")){
			    //如果是PPT文档,则转化为PDF
				command = "libreoffice --convert-to pdf:writer_pdf_Export {src} --outdir {des}";
			} else if(fileType.equals(".jpeg") || fileType.equals(".jpg") || fileType.equals(".gif") || fileType.equals(".png") || fileType.equals(".bmp")){
				//定义图片压缩脚本 规格240x160 //command = "convert -strip -interlace Plane -gaussian-blur 0.02 -quality 85% {src} {src}";
				command = "convert {src} -resize 240x160 {des} "
						.replace("{src}",ctxPath + File.separator + bizPath + File.separator + fileName)
						.replace("{des}", ctxPath + File.separator + bizPath + File.separator + "images" + File.separator + thumborName);
				//执行图片压缩命令
				BashUtil.exec(command);

				//定义图片压缩脚本 规格100x60
				command = "convert {src} -resize 100x60 {des} "
						.replace("{src}",ctxPath + File.separator + bizPath + File.separator + fileName)
						.replace("{des}", ctxPath + File.separator + bizPath + File.separator + "images" + File.separator + thumborName100x60);
				//执行图片压缩命令
				BashUtil.exec(command);

				//定义图片压缩脚本 规格1024x768
				command = "convert {src} -resize 1024x768 {des} "
						.replace("{src}",ctxPath + File.separator + bizPath + File.separator + fileName)
						.replace("{des}", ctxPath + File.separator + bizPath + File.separator + "origin" + File.separator + originName);
				//执行图片压缩命令
				BashUtil.exec(command);

				//执行图片裁剪脚本
				BashUtil.exec("bash /root/jeecg/upFiles/files/thumbor.sh");
			} else {
				command = "";
			}

			//执行shell命令区域
			try{
				//设置命令中的src des
				command = command.replace("{src}",ctxPath + File.separator + bizPath + File.separator + fileName);
				command = command.replace("{des}", ctxPath + File.separator + bizPath + File.separator + convert + File.separator);

				//打印日志
				log.info("command :" + command + " fileType:" + fileType + " ctxPath:" + ctxPath + " bizPath:" + bizPath + " fileName:" + fileName + " convert:" + convert) ;

				//先设置文档可读
				BashUtil.exec("chmod 755 -R " + ctxPath + File.separator + bizPath + File.separator + "*");

				//执行文档转换命令
				BashUtil.exec(command);

                //执行Git Push命令,将本次变动实时同步到远程Git仓库中
                BashUtil.exec("bash /root/jeecg/upFiles/files/start.sh");

			} catch (Exception e){
				log.error(e.getMessage(), e);
			}

			//设置返回消息
			result.setMessage(dbpath);

			//设置返回状态
			result.setSuccess(true);

		} catch (IOException e) {

			result.setSuccess(false);
			result.setMessage("保存文件异常");
			log.error(e.getMessage(), e);

		}

		//返回结果
		return result;

	}

	/**
	 * 预览图片
	 * 请求地址:http://localhost:8080/common/view/{user/20190119/e1fe9925bc315c60addea1b98eb1cb1349547719_1547866868179.jpg}
	 * 
	 * @param request
	 * @param response
	 */
	@GetMapping(value = "/view/**")
	public void view(HttpServletRequest request, HttpServletResponse response) {
		// ISO-8859-1 ==> UTF-8 进行编码转换
		String imgPath = extractPathFromPattern(request);
		// 其余处理略
		InputStream inputStream = null;
		OutputStream outputStream = null;
		try {
			imgPath = imgPath.replace("..", "");
			if (imgPath.endsWith(",")) {
				imgPath = imgPath.substring(0, imgPath.length() - 1);
			}
			response.setContentType("image/jpeg;charset=utf-8");
			String localPath = uploadpath;
			String imgurl = localPath + File.separator + imgPath;
			inputStream = new BufferedInputStream(new FileInputStream(imgurl));
			outputStream = response.getOutputStream();
			byte[] buf = new byte[1024];
			int len;
			while ((len = inputStream.read(buf)) > 0) {
				outputStream.write(buf, 0, len);
			}
			response.flushBuffer();
		} catch (IOException e) {
			log.error("预览图片失败" + e.getMessage());
			// e.printStackTrace();
		} finally {
			if (inputStream != null) {
				try {
					inputStream.close();
				} catch (IOException e) {
					log.error(e.getMessage(), e);
				}
			}
			if (outputStream != null) {
				try {
					outputStream.close();
				} catch (IOException e) {
					log.error(e.getMessage(), e);
				}
			}
		}

	}
	
	/**
	 * 下载文件
	 * 请求地址:http://localhost:8080/common/download/{user/20190119/e1fe9925bc315c60addea1b98eb1cb1349547719_1547866868179.jpg}
	 * 
	 * @param request
	 * @param response
	 * @throws Exception 
	 */
	@GetMapping(value = "/download/**")
	public void download(HttpServletRequest request, HttpServletResponse response) throws Exception {
		// ISO-8859-1 ==> UTF-8 进行编码转换
		String filePath = extractPathFromPattern(request);
		// 其余处理略
		InputStream inputStream = null;
		OutputStream outputStream = null;
		try {
			filePath = filePath.replace("..", "");
			if (filePath.endsWith(",")) {
				filePath = filePath.substring(0, filePath.length() - 1);
			}
			String localPath = uploadpath;
			String downloadFilePath = localPath + File.separator + filePath;
			File file = new File(downloadFilePath);
	         if (file.exists()) {
	        	 response.setContentType("application/force-download");// 设置强制下载不打开            
	 			response.addHeader("Content-Disposition", "attachment;fileName=" + new String(file.getName().getBytes("UTF-8"),"iso-8859-1"));
	 			inputStream = new BufferedInputStream(new FileInputStream(file));
	 			outputStream = response.getOutputStream();
	 			byte[] buf = new byte[1024];
	 			int len;
	 			while ((len = inputStream.read(buf)) > 0) {
	 				outputStream.write(buf, 0, len);
	 			}
	 			response.flushBuffer();
	         }
			
		} catch (Exception e) {
			log.info("文件下载失败" + e.getMessage());
			// e.printStackTrace();
		} finally {
			if (inputStream != null) {
				try {
					inputStream.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if (outputStream != null) {
				try {
					outputStream.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}

	}
	

	/**
	  *  把指定URL后的字符串全部截断当成参数 
	  *  这么做是为了防止URL中包含中文或者特殊字符(/等)时,匹配不了的问题
	 * @param request
	 * @return
	 */
	private static String extractPathFromPattern(final HttpServletRequest request) {
		String path = (String) request.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE);
		String bestMatchPattern = (String) request.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE);
		return new AntPathMatcher().extractPathWithinPattern(bestMatchPattern, path);
	}

}
package org.jeecg.common.util;

import io.netty.util.internal.StringUtil;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.io.InputStream;

/**
 * Bash命令行执行器
 * A001
 * A001A002
 * @Author zhangdaihao
 *
 */
@Slf4j
public class BashUtil {

	/**
	 * @function 执行Shell脚本命令
	 * @param command
	 * @return
	 */
	public static boolean exec(String command) {

		//如果传入参数为空,则直接返回
		if(command.equals("") || command == null){
			return false;
		}

		//执行状态
		int exitStatus = 0;

		// Process可以控制该子进程的执行或获取该子进程的信息
		Process process;

		try {
			log.info("exec cmd : " + command);
			process = Runtime.getRuntime().exec(command);// exec()方法指示Java虚拟机创建一个子进程执行指定的可执行程序,并返回与该子进程对应的Process对象实例。
			// 下面两个可以获取输入输出流
			InputStream errorStream = process.getErrorStream();
			InputStream inputStream = process.getInputStream();
		} catch (IOException e) {
			log.error(" exec cmd error :" + command, e);
			return false;
		}

		try {
			exitStatus = process.waitFor();// 等待子进程完成再往下执行,返回值是子线程执行完毕的返回值,返回0表示正常结束
			// 第二种接受返回值的方法
			int i = process.exitValue(); // 接收执行完毕的返回值
			log.debug("i----" + i);
		} catch (InterruptedException e) {
			log.error("InterruptedException  exec {}", command, e);
			return false;
		}

		if (exitStatus != 0) {
			log.error("exec cmd exitStatus {}", exitStatus);
		} else {
			log.debug("exec cmd exitStatus {}", exitStatus);
		}

		// 销毁子进程
		process.destroy();
		// 子进程设置为空
		process = null;

		//返回执行结果
		return true;
	}

}

 

 

附件上传效果

 

预览效果

 

Tips:因为Office文档在上传完毕时,就已经转换为PDF,PDF文件的URL可以直接通过Iframe配在src进行预览

 

注意此处代码是上传文档后,就是实时同步执行转换PDF操作,但是如果文档过大,可以改为异步执行哈,不然上传的时候一直卡着,小于5M的文档可以,同步执行,转换过程大概就几秒钟,影响不大。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值