文件在线预览方案

您所在的位置:网站首页 html预览word方案 文件在线预览方案

文件在线预览方案

2024-07-11 14:03| 来源: 网络整理| 查看: 265

# 文件在线预览方案 # 一、前言

之前写过一篇文章关于上传目录文件:uni-app系统目录文件上传(非只图片和视频)解决方案 ,这次来解决文件预览问题。

uni-app 是一个使用 Vue.js 开发所有前端应用的框架,开发者编写一套代码,可发布到iOS、Android、H5、以及各种小程序(微信/支付宝/百度/头条/QQ/钉钉)等多个平台。在做业务系统时,不可避免会遇到文件在线预览的需求。这里的文件包括PDF、Word、Excel、PPT、图片等。而在线预览不是下载后再用本地软件或浏览器打开预览,而是直接通过文件流的形式查看。本方案主要解决在线预览问题,以及在uni-app开发过程中遇到一系列问题。

如果有欠缺的地方,或者有更好的方案,还望各位码友多提意见,多多交流,文章最后可以加我。

文件预览,首先会想到pdf预览,前端做pdf预览,首先也会想到pdf.js ,那我们就从pdf.js 说起。

# 二、PDF预览

pdf.js开源地址和在线例子 Github Online Demo

# 2.1 使用方法一

下载插件包,下载地址

解压,拷贝build和web目录到项目hybrid->html目录下,参考uni-app中web-view用法

新建vue组件file-preview.vue

viewerUrl:前端本地viewer.html页面地址 fileUrl:文件流访问地址,参考《三、文件流服务》 import globalConfig from '@/config' export default { data() { return { viewerUrl: '/hybrid/html/web/viewer.html', // viewerUrl: globalConfig.baseUrl + '/pdf/web/viewer.html', allUrl: '' } }, onLoad(options) { let fileUrl = encodeURIComponent( globalConfig.baseUrl + '/api/attachment?name=' + options.name + '&url=' + options.url) this.allUrl = this.viewerUrl + '?file=' + fileUrl } } 1234567891011121314151617181920212223

效果

h5端 显示正常 Android端 显示模糊,并且中文显示不全,其中模糊问题是模拟器原因;但是中文显示问题是真,调试出现两个警告。第二个警告pdf.js默认不显示电子签章(数字签名)问题,查了很多资料也没解决,各位码友有遇到过并且解决了吗? iOS端 出现跨域问题,并且调试出现无法访问pdf.js国际化文件

解决 基于Android和iOS预览出现的各种问题,最根本原因是viewer.html文件放到前端导致加载资源文件丢失问题。针对这个问题,我就在想能不能直接放在spring后端作为静态资源访问文件呢?于是有了下面的方法。

# 2.2 使用方法二

在基于spring mvc的后端代码中,将插件包的build和web文件夹放到webapp下面(新建pdf文件夹),spring boot架构的后端项目同理,放到静态资源目录

在xml文件中配置静态文件访问

修改前端组件file-preview.vue中的viewerUrl,其中globalConfig.baseUrl为代理后端地址的baseUrl。如Vue中proxyTable或nginx代理

viewerUrl: globalConfig.baseUrl + '/pdf/web/viewer.html' 1修改后效果 iOS端 Android端 模糊是模拟器原因,在真机上测试通过 # 三、文件流服务 # 3.1 方法一:tomcat配置

配置tomcat的config目录下的server.xml,在最后的中间添加如下:

port=8090 文件访问服务端口 docBase="/root/" 文件存储目录 服务器上文件会存储到/root/fileData/目录下 文件访问地址为:http://ip地址:8090/fileData/文件名

123456789101112131415# 3.2 方法二:写代码获取服务器文件进行转换

直接上代码

读取目录文件,转换为二进制流 前端组件file-preview.vue中fileUrl为 /api/attachment

核心代码

ios = new FileInputStream(sourceFile); os = response.getOutputStream(); int read = 0; byte[] buffer = new byte[1024 * 1024]; while ((read = ios.read(buffer)) != -1) { os.write(buffer, 0, read); } os.flush(); 12345678

完整代码

@RequestMapping(value = "/api/attachment", method = RequestMethod.GET) public void getFileBytes(@RequestParam("name") String name, @RequestParam("url") String url, HttpServletRequest request, HttpServletResponse response) { response.reset(); response.setContentType("application/octet-stream"); response.setCharacterEncoding("utf-8"); response.setHeader("Content-Disposition", "attachment;filename=" + name); AttachmentVO attachmentVO = new AttachmentVO(); FileInputStream ios = null; OutputStream os = null; try { name = CharsetUtils.toUTF_8(name); url = CharsetUtils.toUTF_8(url); attachmentVO.setUrl(url); attachmentVO.setName(name); File sourceFile = getDictionaryFile(attachmentVO, request); if (null == sourceFile) { // throw new HttpResponseException(300, "附件不存在!"); return; } /** * 判断文件类型 */ /* 获得文件名后缀 */ String ext = ""; if (!"".equals(url) && url.contains(".")) { ext = url.substring(url.lastIndexOf(".") + 1, url.length()).toUpperCase(); } /* 根据文件类型不同进行预览 */ /* 预览pdf */ if ("PDF".equals(ext)) { response.setContentType("application/pdf"); } /** * 将文件写入输出流,显示在界面上,实现预览效果 */ ios = new FileInputStream(sourceFile); os = response.getOutputStream(); int read = 0; byte[] buffer = new byte[1024 * 1024]; while ((read = ios.read(buffer)) != -1) { os.write(buffer, 0, read); } os.flush(); } catch (Exception e) { e.printStackTrace(); try { if (null != ios) { ios.close(); } if (null != os) { os.close(); } } catch (IOException ex) { ex.printStackTrace(); } } } 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061# 四、office文件(Word、Excel、PPT)预览

原理: 搭建OpenOffice服务,将文件转换为pdf,在使用pdf.js预览

# 4.1 搭建openOffice服务

下载Apache_OpenOffice

解压

tar xzvfm Apache_OpenOffice_xxx.tar.gz cd zh-CN/RPMS rpm -ivh *rpm 123运行 # 127.0.0.1只能本机使用该服务 /opt/openoffice4/program/soffice "-accept=socket,host=127.0.0.1,port=8100;urp;" -headless -nofirststartwizard & # 0.0.0.0远程ip能使用 /opt/openoffice4/program/soffice "-accept=socket,host=0.0.0.0,port=8100;urp;" -headless -nofirststartwizard & 1234# 4.2 集成java 在pom.xml添加jar包 org.openoffice juh 4.1.2 org.openoffice jurt 4.1.2 org.openoffice ridl 4.1.2 org.openoffice unoil 4.1.2 com.artofsolving jodconverter 2.2.2 123456789101112131415161718192021222324252627

注意:jodconverter 需要单独下载2.2.2版本,之前的版本都不行,而且maven中央仓库没有2.2.2版本。然后再单独导入。下载地址:https://sourceforge.net/projects/jodconverter/files/

单独导入

mvn install:install-file -Dfile="jodconverter-2.2.2.jar" -DgroupId=com.artofsolving -DartifactId=jodconverter -Dversion=2.2.2 -Dpackaging=jar 1转换代码

核心代码

connection = new SocketOpenOfficeConnection(openofficeHost, openofficePort); connection.connect(); DocumentConverter converter = new StreamOpenOfficeDocumentConverter(connection); converter.convert(sourceFile, pdfFile); 1234

完整代码

/* 利用openOffice将office文件转换为pdf格式, 然后预览doc, docx, xls, xlsx, ppt, pptx */ if ("DOC".equals(ext) || "DOCX".equals(ext) || "XLS".equals(ext) || "XLSX".equals(ext) || "PPT".equals(ext) || "PPTX".equals(ext)) { /* filePath在数据库中是不带文件后缀的, 由于jodConverter必须要识别后缀,所以将服务器中的文件重命名为带后缀的文件 */ // File docFileWithExt = new File(filePath + "." + ext.toLowerCase()); //带后缀的文件 // docFile.renameTo(docFileWithExt); /* 转换之后的文件名 */ String filePath = sourceFile.getPath(); File pdfFile; if (filePath.contains(".")) { pdfFile = new File(filePath.substring(0, filePath.lastIndexOf(".")) + ".pdf"); } else { pdfFile = new File(filePath + ".pdf"); } /* 判断即将要转换的文件是否真实存在 */ if (sourceFile.exists()) { /* 判断该文件是否已经被转换过,若已经转换则直接预览 */ if (!pdfFile.exists()) { OpenOfficeConnection connection; /* 打开OpenOffice连接 */ try { connection = new SocketOpenOfficeConnection(openofficeHost, openofficePort); connection.connect(); } catch (java.net.ConnectException e) { log.warn("openOffice未连接,正在重新连接..."); // 启动OpenOffice的服务 String command = openofficeInstallPath + "program/soffice -headless -accept=\"socket,host=127.0.0.1,port=8100;urp;\" -nofirststartwizard"; Runtime.getRuntime().exec(command); Thread.sleep(1000); connection = new SocketOpenOfficeConnection(8100); connection.connect(); log.warn("openOffice重新连接成功!!!"); } try { // DocumentConverter converter = new OpenOfficeDocumentConverter(connection); DocumentConverter converter = new StreamOpenOfficeDocumentConverter(connection); converter.convert(sourceFile, pdfFile); connection.disconnect(); // filePath = pdfFile.getPath(); // 文件转换之后的路径 sourceFile = pdfFile; response.setContentType("application/pdf"); } catch (OpenOfficeException e) { e.printStackTrace(); // 读取转换文件失败 log.info("读取转换文件失败!!!"); return; } finally { // 发生exception时, connection不会自动切断, 程序会一直挂着 try { if (connection != null) { connection.disconnect(); } } catch (Exception e) { e.printStackTrace(); } } } else { // filePath = pdfFile.getPath(); // 文件已经转换过 sourceFile = pdfFile; response.setContentType("application/pdf"); } } else { log.info("需要预览的文档在服务器中不存在!!!"); // 文件不存在,直接返回 return; } } 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071# 五、图片预览 # 5.1 后端文件流 /* 预览图片 */ if ("PNG".equals(ext) || "JPEG".equals(ext) || "JPG".equals(ext)) { response.setContentType("image/jpeg"); } /* 预览BMP格式的文件 */ if ("BMP".equals(ext)) { response.setContentType("image/bmp"); } /* 预览GIF格式的文件 */ if ("GIF".equals(ext)) { response.setContentType("image/gif"); } 123456789101112# 5.2 前端预览

采用uni-app的uni.previewImage 接口 fileUrl:为文件流访问地址

// 预览图片 uni.previewImage({ urls: [fileUrl], longPressActions: { itemList: ['发送给朋友', '保存图片', '收藏'], success: function(data) { console.log('选中了第' + (data.tapIndex + 1) + '个按钮,第' + (data.index + 1) + '张图片'); }, fail: function(err) { console.log(err.errMsg); } } }) 12345678910111213# 附:完整文件流代码 @RequestMapping(value = "/api/attachment", method = RequestMethod.GET) public void getFileBytes(@RequestParam("name") String name, @RequestParam("url") String url, HttpServletRequest request, HttpServletResponse response) { response.reset(); // 解决IFrame拒绝的问题,无效 // response.setHeader("X-Frame-Options", "SAMEORIGIN"); response.setContentType("application/octet-stream"); response.setCharacterEncoding("utf-8"); response.setHeader("Content-Disposition", "attachment;filename=" + name); AttachmentVO attachmentVO = new AttachmentVO(); FileInputStream ios = null; OutputStream os = null; try { name = CharsetUtils.toUTF_8(name); url = CharsetUtils.toUTF_8(url); attachmentVO.setUrl(url); attachmentVO.setName(name); File sourceFile = getDictionaryFile(attachmentVO, request); if (null == sourceFile) { // throw new HttpResponseException(300, "附件不存在!"); return; } /** * 判断文件类型 */ /* 获得文件名后缀 */ String ext = ""; if (!"".equals(url) && url.contains(".")) { ext = url.substring(url.lastIndexOf(".") + 1, url.length()).toUpperCase(); } /* 根据文件类型不同进行预览 */ /* 预览图片 */ if ("PNG".equals(ext) || "JPEG".equals(ext) || "JPG".equals(ext)) { response.setContentType("image/jpeg"); } /* 预览BMP格式的文件 */ if ("BMP".equals(ext)) { response.setContentType("image/bmp"); } /* 预览GIF格式的文件 */ if ("GIF".equals(ext)) { response.setContentType("image/gif"); } /* 预览pdf */ if ("PDF".equals(ext)) { response.setContentType("application/pdf"); } /* 利用openOffice将office文件转换为pdf格式, 然后预览doc, docx, xls, xlsx, ppt, pptx */ if ("DOC".equals(ext) || "DOCX".equals(ext) || "XLS".equals(ext) || "XLSX".equals(ext) || "PPT".equals(ext) || "PPTX".equals(ext)) { /* filePath在数据库中是不带文件后缀的, 由于jodConverter必须要识别后缀,所以将服务器中的文件重命名为带后缀的文件 */ // File docFileWithExt = new File(filePath + "." + ext.toLowerCase()); //带后缀的文件 // docFile.renameTo(docFileWithExt); /* 转换之后的文件名 */ String filePath = sourceFile.getPath(); File pdfFile; if (filePath.contains(".")) { pdfFile = new File(filePath.substring(0, filePath.lastIndexOf(".")) + ".pdf"); } else { pdfFile = new File(filePath + ".pdf"); } /* 判断即将要转换的文件是否真实存在 */ if (sourceFile.exists()) { /* 判断该文件是否已经被转换过,若已经转换则直接预览 */ if (!pdfFile.exists()) { OpenOfficeConnection connection; /* 打开OpenOffice连接 */ try { connection = new SocketOpenOfficeConnection(openofficeHost, openofficePort); connection.connect(); } catch (java.net.ConnectException e) { log.warn("openOffice未连接,正在重新连接..."); // 启动OpenOffice的服务 String command = openofficeInstallPath + "program/soffice -headless -accept=\"socket,host=127.0.0.1,port=8100;urp;\" -nofirststartwizard"; Runtime.getRuntime().exec(command); Thread.sleep(1000); connection = new SocketOpenOfficeConnection(8100); connection.connect(); log.warn("openOffice重新连接成功!!!"); } try { // DocumentConverter converter = new OpenOfficeDocumentConverter(connection); DocumentConverter converter = new StreamOpenOfficeDocumentConverter(connection); converter.convert(sourceFile, pdfFile); connection.disconnect(); // filePath = pdfFile.getPath(); // 文件转换之后的路径 sourceFile = pdfFile; response.setContentType("application/pdf"); } catch (OpenOfficeException e) { e.printStackTrace(); // 读取转换文件失败 log.info("读取转换文件失败!!!"); return; } finally { // 发生exception时, connection不会自动切断, 程序会一直挂着 try { if (connection != null) { connection.disconnect(); } } catch (Exception e) { e.printStackTrace(); } } } else { // filePath = pdfFile.getPath(); // 文件已经转换过 sourceFile = pdfFile; response.setContentType("application/pdf"); } } else { log.info("需要预览的文档在服务器中不存在!!!"); // 文件不存在,直接返回 return; } } /** * 将文件写入输出流,显示在界面上,实现预览效果 */ ios = new FileInputStream(sourceFile); os = response.getOutputStream(); int read = 0; byte[] buffer = new byte[1024 * 1024]; while ((read = ios.read(buffer)) != -1) { os.write(buffer, 0, read); } os.flush(); } catch (Exception e) { e.printStackTrace(); try { if (null != ios) { ios.close(); } if (null != os) { os.close(); } } catch (IOException ex) { ex.printStackTrace(); } } } 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147 Last Updated: 8/20/2020, 12:51:57 AM

← 消息推送方案



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3