如果想要免费的,可以用 openoffice,实现原理就是: 通过第三方工具openoffice,将word、excel、ppt、txt等文件转换为pdf文件流;当然如果装了Adobe Reader XI,那把pdf直接拖到浏览器页面就可以直接打开预览,前提就是浏览器支持pdf文件浏览。
一、安装openoffice
1. windows环境
openoffice 安装windows 环境
2. linux环境
openoffice 安装 linux环境
二、springboot项目
2.1. 导入依赖
<dependency>
<groupId>com.artofsolving</groupId>
<artifactId>jodconverter</artifactId>
<version>2.2.1</version>
</dependency>
2.2. controller
package com.gblfy.controller;
import com.gblfy.service.IPreviewService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletResponse;
/**
* @author gblfy
* @date 2021-10-28
*/
@Api(tags = "在线预览入口")
@RestController
@RequestMapping("/file/onlinePreview")
public class PreviewController {
@Autowired
private IPreviewService previewService;//在线预览处理类
/**
* 在线预览主入口
*
* @param fileUrl
* @param response
* @throws Exception
*/
@ApiOperation("在线预览主方法")
@PostMapping("/api")
public void onlinePreview(@RequestParam("fileUrl") String fileUrl, HttpServletResponse response) throws Exception {
previewService.onlinePreview(fileUrl, response);
}
}
2.2. 接口
package com.gblfy.service;
import javax.servlet.http.HttpServletResponse;
/**
* 文件在线预览接口
*
* @author gblfy
* @date 2021-10-28
*/
public interface IPreviewService {
void onlinePreview(String url, HttpServletResponse response) throws Exception;
}
2.3. 实现类
package com.gblfy.service.impl;
import com.gblfy.consts.FileTypeConst;
import com.gblfy.service.IPreviewService;
import com.gblfy.utils.FileConvertUtil;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
/**
* 在线预览处理类
*
* @author gblfy
* @date 2021-10-28
*/
@Service
public class PreviewServiceImpl implements IPreviewService {
/**
* 文件在线预览
*
* @param fileUrl 预览的文件路径
* @param response 以pdf文件流的形式返回浏览器完成预览操作
* @throws Exception
*/
@Override
public void onlinePreview(String fileUrl, HttpServletResponse response) throws IOException {
//对url中文件名称进行统一编码,解决400问题
String uRLEncoder = FileConvertUtil.encodeUrlFileName(fileUrl);
//获取文件类型 注意不要携带.
String suffix = FileConvertUtil.suffixFromFileName(uRLEncoder);
if (!FileTypeConst.TXT.equals(suffix) && !FileTypeConst.DOC.equals(suffix)
&& !FileTypeConst.DOCX.equals(suffix) && !FileTypeConst.XLS.equals(suffix)
&& !FileTypeConst.XLSX.equals(suffix) && !FileTypeConst.PPT.equals(suffix)
&& !FileTypeConst.PPTX.equals(suffix)) {
throw new RuntimeException("该文件格式不支持预览");
}
//文件转换处理
InputStream in = FileConvertUtil.convertNetFile(uRLEncoder, suffix);
OutputStream outputStream = response.getOutputStream();
//创建存放文件内容的数组
byte[] buff = new byte[1024];
//所读取的内容使用n来接收
int n;
//当没有读取完时,继续读取,循环
while ((n = in.read(buff)) != -1) {
//将字节数组的数据全部写入到输出流中
outputStream.write(buff, 0, n);
}
//强制将缓存区的数据进行输出
outputStream.flush();
//关流
outputStream.close();
in.close();
}
}
2.4. 格式转换
文件格式转换工具类
package com.gblfy.utils;
import com.artofsolving.jodconverter.DefaultDocumentFormatRegistry;
import com.artofsolving.jodconverter.DocumentConverter;
import com.artofsolving.jodconverter.DocumentFormat;
import com.artofsolving.jodconverter.openoffice.connection.OpenOfficeConnection;
import com.artofsolving.jodconverter.openoffice.connection.SocketOpenOfficeConnection;
import com.artofsolving.jodconverter.openoffice.converter.StreamOpenOfficeDocumentConverter;
import org.springframework.stereotype.Component;
import java.io.*;
import java.net.*;
/**
* 文件格式转换工具类
*
* @author gblfy
* @date 2021-10-28
*/
@Component
public class FileConvertUtil {
/**
* 默认转换后文件后缀
*/
private static final String DEFAULT_SUFFIX = "pdf";
/**
* openoffice_port
*/
private static final Integer OPENOFFICE_PORT = 8100;
/**
* 方法描述 office文档转换为PDF(处理本地文件)
*
* @param sourcePath 源文件路径
* @param suffix 源文件后缀
* @return InputStream 转换后文件输入流
* @author tarzan
*/
public static InputStream convertLocaleFile(String sourcePath, String suffix) throws Exception {
File inputFile = new File(sourcePath);
InputStream inputStream = new FileInputStream(inputFile);
return covertCommonByStream(inputStream, suffix);
}
/**
* 方法描述 office文档转换为PDF(处理网络文件)
*
* @param netFileUrl 网络文件路径
* @param suffix 文件后缀
* @return InputStream 转换后文件输入流
* @author tarzan
*/
public static InputStream convertNetFile(String netFileUrl, String suffix) throws IOException {
// 创建URL
URL url = new URL(netFileUrl);
// 试图连接并取得返回状态码
URLConnection urlconn = url.openConnection();
urlconn.connect();
HttpURLConnection httpconn = (HttpURLConnection) urlconn;
int httpResult = httpconn.getResponseCode();
if (httpResult == HttpURLConnection.HTTP_OK) {
InputStream inputStream = urlconn.getInputStream();
//文件转换
return covertCommonByStream(inputStream, suffix);
}
return null;
}
/**
* 方法描述 将文件以流的形式转换
*
* @param inputStream 源文件输入流
* @param suffix 源文件后缀
* @return InputStream 转换后文件输入流
* @author tarzan
*/
public static InputStream covertCommonByStream(InputStream inputStream, String suffix) throws ConnectException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
OpenOfficeConnection connection = new SocketOpenOfficeConnection(OPENOFFICE_PORT);
connection.connect();
DocumentConverter converter = new StreamOpenOfficeDocumentConverter(connection);
DefaultDocumentFormatRegistry formatReg = new DefaultDocumentFormatRegistry();
DocumentFormat targetFormat = formatReg.getFormatByFileExtension(DEFAULT_SUFFIX);
DocumentFormat sourceFormat = formatReg.getFormatByFileExtension(suffix);
converter.convert(inputStream, sourceFormat, out, targetFormat);
connection.disconnect();
return outputStreamConvertInputStream(out);
}
/**
* 方法描述 outputStream转inputStream
*
* @author tarzan
*/
public static ByteArrayInputStream outputStreamConvertInputStream(final OutputStream out) {
ByteArrayOutputStream baos = (ByteArrayOutputStream) out;
return new ByteArrayInputStream(baos.toByteArray());
}
/**
* 通过文件名获取文件后缀
*
* @param fileName 文件名称
* @return 文件后缀
*/
public static String suffixFromFileName(String fileName) {
return fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();
}
/**
* 对url中的文件名进行UTF-8编码
*
* @param url url
* @return 文件名编码后的url
*/
public static String encodeUrlFileName(String url) {
String noQueryUrl = url.substring(0, url.contains("?") ? url.indexOf("?") : url.length());
int fileNameStartIndex = noQueryUrl.lastIndexOf('/') + 1;
int fileNameEndIndex = noQueryUrl.lastIndexOf('.');
String encodedFileName;
try {
encodedFileName = URLEncoder.encode(noQueryUrl.substring(fileNameStartIndex, fileNameEndIndex), "UTF-8");
} catch (UnsupportedEncodingException e) {
return null;
}
return url.substring(0, fileNameStartIndex) + encodedFileName + url.substring(fileNameEndIndex);
}
// public static void main(String[] args) {
// String url ="http://127.0.0.1:8080/flies/新建MicrosoftExcel工作表.xlsx";
// String ii = encodeUrlFileName(url);
// System.out.println(ii);
// }
}
2.5. 配置类
package com.gblfy.config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* web 配置类
*
* @author gblfy
* @Date 2019/11/12日 下午5:03:32
*/
@Configuration
public class WebConfig implements WebMvcConfigurer {
/**
* 在配置文件中配置的文件保存路径
*/
@Value("${files.location}")
private String files;
/**
* 静态资源映射
*/
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
//本应用\static\editor\fonts
registry.addResourceHandler("/flies/**").addResourceLocations("file:" + files);
}
}
2.6. 扩展配置
说明:添加扩展配置原因 解决jodconverter 2.2.1 版本不支持docx、xlsx、pptx 转换成PDF格式异常
package com.artofsolving.jodconverter;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
* @description: 重写 BasicDocumentFormatRegistry 文档格式
*
* @Author: gblfy
* @Data: 2021-10-27
**/
public class BasicDocumentFormatRegistry implements DocumentFormatRegistry {
private List/* <DocumentFormat> */ documentFormats = new ArrayList();
public void addDocumentFormat(DocumentFormat documentFormat) {
documentFormats.add(documentFormat);
}
protected List/* <DocumentFormat> */ getDocumentFormats() {
return documentFormats;
}
/**
* @param extension the file extension
* @return the DocumentFormat for this extension, or null if the extension
* is not mapped
*/
@Override
public DocumentFormat getFormatByFileExtension(String extension) {
if (extension == null) {
return null;
}
//将文件名后缀统一转化
if (extension.indexOf("doc") >= 0) {
extension = "doc";
}
if (extension.indexOf("ppt") >= 0) {
extension = "ppt";
}
if (extension.indexOf("xls") >= 0) {
extension = "xls";
}
String lowerExtension = extension.toLowerCase();
for (Iterator it = documentFormats.iterator(); it.hasNext(); ) {
DocumentFormat format = (DocumentFormat) it.next();
if (format.getFileExtension().equals(lowerExtension)) {
return format;
}
}
return null;
}
@Override
public DocumentFormat getFormatByMimeType(String mimeType) {
for (Iterator it = documentFormats.iterator(); it.hasNext(); ) {
DocumentFormat format = (DocumentFormat) it.next();
if (format.getMimeType().equals(mimeType)) {
return format;
}
}
return null;
}
}
2.7. 全局配置
files:
location: D:/files/
mapping: /flies/
```bash
files:
location: /app/files/
mapping: /flies/
安装字体 生成PDF乱码问题解决方案
2.8. 项目源码
https://gitee.com/gb_90/online-preview
2.9. 项目拉取
git clone git@gitee.com:gb_90/online-preview.git
2.10.效果图
三、源码心得分享
3.1. 适配兼容
日常office 格式文件转换可以满足,支持文件格式很多, 例如:doc、docx、xls、xlsx、ppt、pptx、txt 等,这里不一一列举
3.2. 兼容不足
3.3. 解决方案
修改源码预览之前,对将要预览的尺寸大小,先办法获取到,然后再动态设置就好
|