企业级-pdf预览-前后端
作者:fyupeng
技术专栏:☞ https://github.com/fyupeng
项目地址:☞ https://github.com/fyupeng/distributed-blog-system-api
留给读者
本文
一、介绍
对于PDF预览,有很多开发者都遇到过头疼的难题,今天给大家介绍一个比较成熟的浏览器直接提供的预览嵌入Vue组件。
二、代码
- 快速使用:
html
渲染:
<el-dialog
:lock-scroll="false"
custom-class="imgPreview_dia"
:show-close="true"
top="5vh"
width="90vw"
v-model="dialogVisible"
>
<filePreview :fileUrl="fileUrl" width="90vw" height="90vh"></filePreview>
</el-dialog>
css
样式:
.imgPreview_dia {
border-radius: 0 !important;
margin: 0;
left: 5vw;
}
js
处理:
const dialogVisible = ref(false);
const fileUrl = ref("");
const handleYulan = (index: number, row: object) => {
fileUrl.value =
// showDocFile() +
"http://localhost:8086/machine/commonFile/notice/showDocFile" +
"?fileId=" +
row.fileId +
"&pripid=" +
props.initData?.pripid +
"&time=" +
new Date().getTime();
// fileUrl.value =
// showDocFile() +
// "?docId=2516&gid=4055fb556a9c440590464017f28aae0e&time=1691460960121";
dialogVisible.value = true;
};
- 模板:
后端处理:
public Boolean showNoticeDocFile(String fileId, HttpServletResponse response) {
FileInputStream input = null;
OutputStream output = null;
try {
File file = getNoticeDocRowFile(fileId);
if (file == null || !file.exists()) {
return false;
}
input = new FileInputStream(file);
int i = input.available(); // 得到文件大小
byte[] data = new byte[i];
input.read(data); // 读数据
response.setContentType("application/pdf"); // 设置返回的文件类型
response.addHeader("Content-Length", String.valueOf(data.length)); //文件大小
output = response.getOutputStream(); // 得到向客户端输出二进制数据的对象
output.write(data); // 输出数据
output.flush();
file.delete();
return true;
} catch (Exception e) {
logger.error("==showFile==文件信息回显失败!fileId:{}", fileId, e);
return false;
} finally {
try {
if (input != null)
input.close();
if (output != null)
output.close();
} catch (IOException e) {
logger.error(e.getMessage(), e);
}
}
}
前端处理:
filePreview.vue
<template>
<div class="wrap" v-loading="isLoading">
<div class="pdf-container">
<iframe
id="doc-iframe"
:src="url"
:style="{ width: prop.width, height: prop.height, background: '#fff' }"
class="parintDetailDoc"
ref="iframeRef"
></iframe>
</div>
</div>
</template>
<script lang="ts" setup>
import { ref, reactive, watch, defineProps, defineEmits, onMounted } from "vue";
import { ElMessage } from "element-plus";
const emits = defineEmits(["loaded"]);
const prop = defineProps({
fileUrl: {
type: String,
default: "",
},
width: {
type: String,
default: "800px",
},
height: {
type: String,
default: "800px",
},
});
const isLoading = ref(true);
const url = ref("");
watch(
() => prop.fileUrl,
() => {
url.value = prop.fileUrl;
console.log("--------prop.fileUrl", prop.fileUrl);
},
{ immediate: true }
);
onMounted(() => {
let iframeDom = document.getElementById("doc-iframe") || {};
iframeDom.onload = function () {
isLoading.value = false;
emits("loaded");
};
});
</script>
<style scoped>
.parintDetailDoc::-webkit-scrollbar {
display: none;
}
.parintDetailDoc {
border: none;
max-width: 100%;
}
</style>
三、总结
简洁、高效、实用!