前端JQuery获取Java后端文件流实现常规附件预览功能
- 项目背景
- 1. Java后端处理附件
- 1.1 将word文档转换为pdf格式
- 1.2 将文件流返回前端
- 2. 前端处理附件预览(JQuery)
- 2.1 预览pdf文件
- 2.2 预览ofd文件
- 2.3 预览图片、txt文档
- 共勉。
项目背景
目前维护的项目是个远古的SpringMVC项目,前端使用的是JQuery和HTML,与Vue相比维护比较复杂,功能实现上没有那么丰富。在做附件预览的需求时,考虑不借助第三方预览服务,通过开源组件实现,需要借助以下服务依赖:
1)Java:引入aspose.words依赖(支持将word文档转换为pdf格式)
注意:需要引入license
1. Java后端处理附件
1.1 将word文档转换为pdf格式
1)在resource下新增license.xml
<License><Data><Products><Product>Aspose.Total for Java</Product><Product>Aspose.Words for Java</Product></Products><EditionType>Enterprise</EditionType><SubscriptionExpiry>20991231</SubscriptionExpiry><LicenseExpiry>20991231</LicenseExpiry><SerialNumber>8bfe198c-7f0c-4ef8-8ff0-acc3237bf0d7</SerialNumber></Data><Signature>sNLLKGMUdF0r8O1kKilWAGdgfs2BvJb/2Xp8p5iuDVfZXmhppo+d0Ran1P9TKdjV4ABwAgKXxJ3jcQTqE/2IRfqwnPf8itN8aFZlV3TJPYeD3yWE7IT55Gz6EijUpC7aKeoohTb4w2fpox58wWoF3SNp6sK6jDfiAUGEHYJ9pjU=</Signature>
</License>
2)word转pdf工具类
/*** @program: Mickey* @description: pdf工具类**/
public class WordToPdfUtil {public static byte[] toPdfBytes(HttpServletRequest req, InputStream inputstream) throws IOException {ByteArrayOutputStream bos = new ByteArrayOutputStream();byte[] b = null;try {//认证aspose-word,否则转换的pdf会有水印if (!getWordLicense(req)) {return null;}LoadOptions options = new LoadOptions();options.setLoadFormat(LoadFormat.DOC);Document doc = new Document(inputstream, options);doc.save(bos, SaveFormat.PDF);b = bos.toByteArray();} catch (Exception e) {e.printStackTrace();throw new RuntimeException("word转换pdf出错!");} finally {bos.close();}return b;}/*** 获取aspose-word授权** @return*/public static boolean getWordLicense(HttpServletRequest req) {boolean result = false;InputStream is = null;try {//获取认证文件,并转为输入流is = new FileInputStream(req.getSession().getServletContext().getRealPath("") + File.separator + "downFile/pdfFile" + File.separator + "license.xml");//创建密钥认证对象License aposeLic = new License();//进行认证ssaposeLic.setLicense(is);result = true;} catch (Exception e) {e.printStackTrace();}return result;}
}
1.2 将文件流返回前端
try (InputStream in = new FileInputStream(new File("文件路径"))) {// 预览附件类型白名单List<String> whiteFileTypeList = Arrays.asList(DOC_SUFFIX, DOCX_SUFFIX, PDF_SUFFIX, TXT_SUFFIX, OFD_SUFFIX, PNG_SUFFIX, JPG_SUFFIX, JPEG_SUFFIX);// 不支持附件预览的类型if (StringUtils.isNotBlank(suffix) && !whiteFileTypeList.contains(suffix)) {throw new RuntimeException("不支持的附件预览类型,请下载后查看!");}String fileName = "预览附件名称";byte[] toPdfBytes;// word文档类型进行格式转换if (StringUtils.equals(DOC_SUFFIX, suffix) || StringUtils.equals(DOCX_SUFFIX, suffix)) {toPdfBytes = WordToPdfUtil.toPdfBytes(request, in);} else {toPdfBytes = readInputStream(in);if (StringUtils.equals(PNG_SUFFIX, suffix) || StringUtils.equals(JPG_SUFFIX, suffix) || StringUtils.equals(JPEG_SUFFIX, suffix)) {String base64Str = Base64Utils.encodeToString(toPdfBytes);model.put("base64Str", base64Str);}if (StringUtils.equals(TXT_SUFFIX, suffix)) {model.put("txtView", toPdfBytes);}}if (toPdfBytes != null) {try {String contextPath = request.getContextPath();String basePath = request.getSession().getServletContext().getRealPath(File.separator);File outFile = new File(basePath + File.separator + "temp" + File.separator + "fileView");if (!outFile.isDirectory()) {if (!outFile.exists()) {boolean b = outFile.mkdirs();}}FileOutputStream fo = new FileOutputStream(outFile + File.separator + "附件id" + ".pdf");BufferedOutputStream out = new BufferedOutputStream(fo);out.write(toPdfBytes, 0, toPdfBytes.length);out.flush();out.close();return contextPath + File.separator + "temp" + File.separator + "fileView" + File.separator + "附件id" + ".pdf";} catch (IOException e) {e.printStackTrace();}}
} catch (IOException e) {log.error("附件处理异常", e);
}
2. 前端处理附件预览(JQuery)
2.1 预览pdf文件
引入PDFView组件
<iframe id="pdfFrame" src="${base}/pdfView/web/viewer.html?file=${viewFilePath}" width="900" height="530"></iframe>
2.2 预览ofd文件
引入ofd.js依赖,支持ofd文件查看
<div class="ofdContainer" id="ofdContainer" style="width: 900px; height: 530px; overflow-y: scroll;"></div>
$(function() {// ofd文件预览if (suffix && suffix === 'ofd') {var xhr = new XMLHttpRequest();xhr.open('POST', '附件下载地址', true);xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');xhr.responseType = 'blob';xhr.send("id=" + 附件id);xhr.onload = function(e) {if (this.status === 200) {var blob = new Blob([this.response], {type: 'application/ofd'});// 处理文件流,比如使用 FileReader 进行读取或者直接下载const file = new File([blob], fileName + '.ofd', { type: blob.type });ofd.parseOfdDocument({ofd: file,success: function (res) {const screenWidth = 800;const ofdRenderRes = ofd.renderOfd(screenWidth, res[0]);let ofdContainerDiv = document.getElementById('ofdContainer');// 清空元素ofdContainerDiv.innerHTML = '';for (const item of ofdRenderRes) {ofdContainerDiv.appendChild(item);}},fail: function (err) {console.error(err);},});}};}
})
2.3 预览图片、txt文档
1)将后端获取的文件流转换为Base64格式,前端展示图片
<img src="data:image/jpeg;base64,${base64Str!}" style="width: 900px; height: 530px; overflow-y: scroll;" />
2)展示txt文档
<pre class="txtContainer" id="txtContainer" style="width: 900px; height: 530px; overflow-y: scroll; text-align: left;"></pre>
fetch('替换为你的后端TXT文件下载地址' + 附件id).then(response => response.text()).then(text => {document.getElementById('txtContainer').textContent = text;}).catch(error => console.error('读取文件出错:', error));