前端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();
//进行认证ss
aposeLic.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));