一、需求分析
在工作中,有个需求:
- 前端上传PDF文件,需要转成base64编码,传给后端。
- 查看的时候,后端返回base64编码,前端实现PDF预览。
目前有个缺点,PDF文件如果大于2M,就预览不成功了。
二、实现方法
1、使用el-upload组件实现上传按钮
<el-upload :multiple="false" accept=".pdf" action="#" :http-request="httpRequest" :show-file-list="false" > <el-button size="mini" type="primary">点击上传</el-button> </el-upload>
2、使用el-table实现上传后的文件列表
<el-table :data="files" style="width: 100%"> <el-table-column type="index" width="100"> </el-table-column> <el-table-column prop="fileName" label="文件名称"> </el-table-column> <el-table-column fixed="right" label="操作" width="200"> <template slot-scope="scope"> <el-button @click="lookFile(scope.row.fileId)" type="text" size="small" >查看</el-button > <el-button @click="delFile(scope.index)" type="text" size="small" >删除</el-button > </template> </el-table-column> </el-table>
3、使用el-dialog弹窗实现pdf文件预览
<el-dialog title="文件预览" :visible.sync="dialogVisible" width="1000px"> <div style="height: 80vh"> <iframe width="100%" height="100%" :src="`data:application/pdf;base64, ${file}`" ></iframe> </div> </el-dialog>
4、定义的data数据
<script> export default { data() { return { dialogVisible: false, //预览弹窗 file: "", //预览文件 files: [], //已上传的文件列表 }; }, }; </script>
5、覆盖默认的上传行为,自定义上传
httpRequest(data) { // 调用转方法base64 this.getBase64(data.file) .then((resBase64) => { console.log(resBase64) //获取文件,不带data:application/pdf;base64, 前缀 this.file = resBase64.split(",")[1]; //获取文件名称 this.fileName = data.file.name; this.files.push({ fileId: 1, fileName: this.fileName, file:this.file }); //调用上传接口,这里暂时不调用 // this.upload(); }) .catch((err) => { console.log(err); }); },
6、转base64码方法
getBase64(file) { return new Promise((resolve, reject) => { const reader = new FileReader(); let fileResult = ""; reader.readAsDataURL(file); // 开始转码 reader.onload = () => { fileResult = reader.result; }; // 转码失败 reader.onerror = (error) => { reject(error); }; // 转码结束 reader.onloadend = () => { resolve(fileResult); }; }); },
7、点击预览方法
这里只是模拟,后面需要调用后端接口获取数据
//预览 lookFile(fileId) { let that = this; that.file = fileId.file; that.dialogVisible = true; },
8、调用接口上传文件
upload() { let that = this; let { file, fileName } = that; //这里调用后端接口,根据自己项目修改,传递参数为base64文件,及文件名称 this.$api .upload({ file, fileName }) .then((res) => { if (res.data.code == 200) { let result = res.data.data; //这里是接口返回fileId,fileName,然后添加到文件列表数组里 that.files.push({ fileId: result.fileId, fileName: result.fileName, }); that.$message.success("文件上传成功"); } }) .catch((err) => { console.log(err); }); },
三、全部代码
具体实现代码如下:
<template> <div> <!-- 选择文件 --> <el-upload :multiple="false" accept=".pdf" action="#" :http-request="httpRequest" :show-file-list="false" > <el-button size="mini" type="primary">点击上传</el-button> </el-upload> <!-- 文件列表 --> <el-table :data="files" style="width: 100%"> <el-table-column type="index" width="100"> </el-table-column> <el-table-column prop="fileName" label="文件名称"> </el-table-column> <el-table-column fixed="right" label="操作" width="200"> <template slot-scope="scope"> <el-button @click="lookFile(scope.row.fileId)" type="text" size="small" >查看</el-button > <el-button @click="delFile(scope.index)" type="text" size="small" >删除</el-button > </template> </el-table-column> </el-table> <!-- 文件预览 --> <el-dialog title="文件预览" :visible.sync="dialogVisible" width="1000px"> <div style="height: 80vh"> <iframe width="100%" height="100%" :src="`data:application/pdf;base64, ${file}`" ></iframe> </div> </el-dialog> </div> </template> <script> export default { data() { return { dialogVisible: false, //预览弹窗 file: "", //预览文件 files: [], //已上传的文件列表 }; }, methods: { //删除 delFile(index) { this.files.splice(index, 1); }, //预览 lookFile(fileId) { let that = this; //这里调用后端接口,根据自己项目修改,传递参数为fileId this.$api .getFile({ fileId }) .then((res) => { if (res.data.code == 200) { //这里是接口返回的文件base64,不带data:application/pdf;base64, 前缀 that.file = res.data.data; that.dialogVisible = true; } }) .catch((err) => { console.log(err); }); }, //覆盖默认的上传行为,可以自定义上传的实现 httpRequest(data) { // 调用转方法base64 this.getBase64(data.file) .then((resBase64) => { //获取文件,不带data:application/pdf;base64, 前缀 this.file = resBase64.split(",")[1]; //获取文件名称 this.fileName = data.file.name; //调用上传接口 that.upload(); }) .catch((err) => { console.log(err); }); }, //调用接口上传文件 upload() { let that = this; let { file, fileName } = that; //这里调用后端接口,根据自己项目修改,传递参数为base64文件,及文件名称 this.$api .upload({ file, fileName }) .then((res) => { if (res.data.code == 200) { let result = res.data.data; //这里是接口返回fileId,fileName,然后添加到文件列表数组里 that.files.push({ fileId: result.fileId, fileName: result.fileName, }); that.$message.success("文件上传成功"); } }) .catch((err) => { console.log(err); }); }, // 转base64码 getBase64(file) { return new Promise((resolve, reject) => { const reader = new FileReader(); let fileResult = ""; reader.readAsDataURL(file); // 开始转码 reader.onload = () => { fileResult = reader.result; }; // 转码失败 reader.onerror = (error) => { reject(error); }; // 转码结束 reader.onloadend = () => { resolve(fileResult); }; }); }, }, }; </script> <style scoped> iframe { border: 0 none; } ::v-deep .el-dialoog__body { padding: 8px !important; box-sizing: border-box; } </style>
四、效果展示