场景 SpringBoot+Vue+OpenOffice实现文档管理(文档上传、下载、在线预览): SpringBoot+Vue+OpenOffice实现文档管理(文档上传、下载、在线预览)_霸道流氓气质的博客-CSDN博客_vue ope
SpringBoot+Vue+OpenOffice实现文档管理(文档上传、下载、在线预览):
SpringBoot+Vue+OpenOffice实现文档管理(文档上传、下载、在线预览)_霸道流氓气质的博客-CSDN博客_vue openoffice
上面在使用OpenOffice实现doc、excel、ppt等文档的管理和预览。
除此之外可用kkFileView实现包括且更多文档的预览。
kkFileView为文件文档在线预览解决方案,该项目使用流行的Spring Boot搭建,易上手和部署,
基本支持主流办公文档的在线预览,如doc,docx,xls,xlsx,ppt,pptx,pdf,txt,zip,rar,图片,视频,音频等等。
gitee地址:
具体参考文档:
这里是windows电脑,所以直接下载发行版本并解压运行即可
解压之后找到bin下bat,双击启动即可
启动成功之后访问:
出现如下界面则成功
当您的项目内需要预览文件时,只需要调用浏览器打开本项目的预览接口,并传入须要预览文件的url
var url = 'Http://127.0.0.1:8080/file/test.txt'; //要预览文件的访问地址 window.open('http://127.0.0.1:8012/onlinePreview?url='+encodeURIComponent(base64Encode(url)));
注:
博客:
霸道流氓气质的博客_CSDN博客-C#,架构之路,SpringBoot领域博主
关注公众号
霸道的程序猿
获取编程相关电子书、教程推送与免费下载。
若依前后端分离版手把手教你本地搭建环境并运行项目_霸道流氓气质的博客-CSDN博客_运行若依分离版
基于上面搭建起来架构的基础上。
设计数据库表
DROP TABLE IF EXISTS `bus_file_preview`;CREATE TABLE `bus_file_preview` ( `id` bigint(0) NOT NULL AUTO_INCREMENT COMMENT '主键', `file_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '文件名', `preview_server_url` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '预览服务地址', `file_path` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '文件磁盘路径', `file_url` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '文件url', `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', `create_by` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL COMMENT '创建人', `update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新时间', `update_by` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL COMMENT '更新人', `remark` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL COMMENT '备注', PRIMARY KEY (`id`) USING BTREE) ENGINE = InnoDB AUTO_INCREMENT = 15 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '文件上传与预览' ROW_FORMAT = Dynamic;SET FOREIGN_KEY_CHECKS = 1;
表结构
使用若依自带代码生成工具生成代码,下面展示部分代码
实体类BusFilePreview
import org.apache.commons.lang3.builder.ToStringBuilder;import org.apache.commons.lang3.builder.ToStringStyle;import com.ruoyi.common.annotation.Excel;import com.ruoyi.common.core.domain.BaseEntity;public class BusFilePreview extends BaseEntity{ private static final long serialVersionUID = 1L; private Long id; @Excel(name = "文件名") private String fileName; @Excel(name = "预览服务地址") private String previewServerUrl; @Excel(name = "文件url") private String fileUrl; @Excel(name = "文件磁盘路径") private String filePath; public void setId(Long id) { this.id = id; } public Long getId() { return id; } public void setFileName(String fileName) { this.fileName = fileName; } public String getFileName() { return fileName; } public void setPreviewServerUrl(String previewServerUrl) { this.previewServerUrl = previewServerUrl; } public String getPreviewServerUrl() { return previewServerUrl; } public void setFileUrl(String fileUrl) { this.fileUrl = fileUrl; } public String getFileUrl() { return fileUrl; } public void setFilePath(String filePath) { this.filePath = filePath; } public String getFilePath() { return filePath; } @Override public String toString() { return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) .append("id", getId()) .append("fileName", getFileName()) .append("previewServerUrl", getPreviewServerUrl()) .append("fileUrl", getFileUrl()) .append("createTime", getCreateTime()) .append("createBy", getCreateBy()) .append("updateTime", getUpdateTime()) .append("updateBy", getUpdateBy()) .append("remark", getRemark()) .toString(); }}
前端添加el-upload
上传 提示:仅允许导入".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", ".pdf", ".mp3",".mp4",".wav"格式文件!
并设置各回调事件,事件实现
// 文件上传失败 uploadError(err) { this.btnLoding = false; this.$message.error(res.msg); }, // 上传中 uploadProgress(e) { this.btnLoding = true; }, // 文件上传之前 beforeUpload(file) { const fileName = file.name; const fileType = fileName.substring(fileName.lastIndexOf(".")); const whiteList = [ ".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", ".pdf", ".mp3", ".mp4", ".wav", ]; //array.indexOf此方法判断数组中是否存在某个值,如果存在返回数组元素的下标,否则返回-1。 if (whiteList.indexOf(fileType) === -1) { this.$message.error("只允许如下文件类型:" + whiteList.toString()); return false; // 不处理 } else { this.form.fileName = file.name; } }, // 文件上传成功 uploadSuccess(res, file, fileList) { this.form.previewServerUrl = res.previewServerUrl; this.form.fileUrl = res.fileUrl; this.form.filePath = res.filePath; this.btnLoding = false; this.fileList = fileList; this.$message(res.msg); }, beyond(file, fileList) { this.$message({ message: "最多上传一个文件", type: "warning", }); }, // 移除选择的文件 fileRemove(file, fileList) { this.btnLoding = false; this.reset(); this.fileList = []; },
重点关注文件上传之前的beforeUpload和文件上传成功的uploadSuccess
上传之前获取文件名和后缀名,然后判断是否为允许的文件类型,如果允许,获取文件名。
文件上传成功之后获取后台接口返回的文件预览服务地址和文件预览url以及磁盘路径三个参数。
其中文件预览服务地址指的是kkFileView的ip和端口号以及预览的url,比如这里是与后台服务放在了一起,
所以previewServerUrl为http://127.0.0.1:8012/onlinePreview?url=
文件预览url为调用kkFileView预览时传递的参数,比如
http://127.0.0.1:9090/profile/upload/2022/12/10/a28ffa19-9982-42d2-8766-1feb274c5bb7.doc
文件磁盘路径映射为网络url可以参考
SpringBoot中通过重写WEBmvcConfigurer的方法配置静态资源映射实现图片上传后返回网络Url:
SpringBoot中通过重写WebMvcConfigurer的方法配置静态资源映射实现图片上传后返回网络Url_霸道流氓气质的博客-CSDN博客
这里后台将预览文件的网络url单独返回,是因为在前端进行预览时,需要对url参数进行base64编码
如果不进行编码预览会有问题,会提示
Illegal base64 character 3a
这点官网有说明
代码实现
@PostMapping("/uploadPreviewFile") public ajaxResult uploadPreviewFile(@Param("file") MultipartFile file) { AjaxResult ajaxResult = AjaxResult.success(); try { //D:/ruoyi/uploadPath/upload/2022/12/10/ String path = RuoYiConfig.getUploadPath() + "/" + DateUtils.datePath() + "/"; FileUtils.check_folder(path); // 上传后的文件名称 //423208ab-2171-4631-9e08-382c00aacc43.doc String auth_file_name = UploadUtil.save_file_withAllow(file, path ,allowFiles); if (StringUtils.isEmpty(auth_file_name)){ return AjaxResult.error(httpstatus.BAD_REQUEST, "文件格式不合法"); } ajaxResult.put("code", 200); ajaxResult.put("message", "成功"); ajaxResult.put("fileName", auth_file_name); ajaxResult.put("filePath", path + auth_file_name); //serverConfig.getUrl() http://127.0.0.1:9090 //Constants.RESOURCE_PREFIX /profile //RuoYiConfig.getUploadPathPre() /upload //File.separator / //DateUtils.datePath() /2022/12/10 //auth_file_name a28ffa19-9982-42d2-8766-1feb274c5bb7.doc //url http://127.0.0.1:9090/profile/upload/2022/12/10/a28ffa19-9982-42d2-8766-1feb274c5bb7.doc String fileUrl = serverConfig.getUrl()+ Constants.RESOURCE_PREFIX + RuoYiConfig.getUploadPathPre() + File.separator + DateUtils.datePath() + File.separator + auth_file_name; String previewServerUrl = Constants.HTTP + previewConfig.getServerIp() +":" +previewConfig.getServerPort() + Constants.PREVIEW_SERVER_URL; ajaxResult.put("previewServerUrl", previewServerUrl); ajaxResult.put("fileUrl", fileUrl); } catch (IOException e) { ajaxResult.put("code", 400); ajaxResult.put("message", "上传失败"); e.printStackTrace(); } return ajaxResult; }
为方便更清晰的调试理解,这里在生成网络url时标注了每一步的参数
首先调用若依的工具类获取并检查文件上传目录,这里的RuoYiConfig.getUploadPath()配置的是D:/ruoyi/uploadPath
然后最终path的值为D:/ruoyi/uploadPath/upload/2022/12/10/
然后调用文件上传方法,这里新建了一个重载方法,传递了允许上传的文件类型,若依自带的方法该参数是写死的
public static String save_file_withAllow(MultipartFile file, String path ,String[] allowFiles) throws IOException { String filename=file.getOriginalFilename(); //后缀名校验 String suffix = filename.substring(filename.indexOf(".")); List allowFileList = new ArrayList<>(Arrays.asList(allowFiles)); if (!allowFileList.contains(suffix)){ return null; } filename = UUID.randomUUID().toString() + suffix; File file_temp=new File(path,filename); if (!file_temp.getParentFile().exists()) { file_temp.getParentFile().mkdir(); } if (file_temp.exists()) { file_temp.delete(); } file_temp.createNewFile(); file.transferTo(file_temp); return file_temp.getName(); }
允许上传的格式需要声明
private static String[] allowFiles = {".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", ".pdf",".mp3",".mp4",".wav" };
上传成功之后获取到文件的文件名,比如423208ab-2171-4631-9e08-382c00aacc43.doc
然后生成文件预览网络url
//serverConfig.getUrl() http://127.0.0.1:9090 //Constants.RESOURCE_PREFIX /profile //RuoYiConfig.getUploadPathPre() /upload //File.separator / //DateUtils.datePath() /2022/12/10 //auth_file_name a28ffa19-9982-42d2-8766-1feb274c5bb7.doc //url http://127.0.0.1:9090/profile/upload/2022/12/10/a28ffa19-9982-42d2-8766-1feb274c5bb7.doc String fileUrl = serverConfig.getUrl()+ Constants.RESOURCE_PREFIX + RuoYiConfig.getUploadPathPre() + File.separator + DateUtils.datePath() + File.separator + auth_file_name;
这里的serverConfig是若依自带获取服务相关配置,其它的就是一些常量配置。
RuoYiConfig.getUploadPathPre() 是自己新增的获取上传路径的前缀
public static String getUploadPathPre() { return "/upload"; }
最后返回kkFileView服务预览的ip和端口以及前缀
String previewServerUrl = Constants.HTTP + previewConfig.getServerIp() +":" +previewConfig.getServerPort() + Constants.PREVIEW_SERVER_URL;
这里将ip和端口写在配置文件中
#文件预览相关配置preview: serverIp: 127.0.0.1 serverPort: 8012
然后新增配置文件获取
import org.springframework.boot.context.properties.ConfigurationProperties;import org.springframework.stereotype.Component;@Component@ConfigurationProperties(prefix = "preview")public class PreviewConfig { private String serverIp; private String serverPort; public String getServerIp() { return serverIp; } public void setServerIp(String serverIp) { this.serverIp = serverIp; } public String getServerPort() { return serverPort; } public void setServerPort(String serverPort) { this.serverPort = serverPort; }}
最终返回的previewServerUrl为
http://127.0.0.1:8012/onlinePreview?url=
上传成功之后,前端获取返回参数并赋值到form中,前端点击提交按钮时
submitForm() { this.$refs["form"].validate((valid) => { if (valid) { if (this.form.id != null) { updatePreview(this.form).then((response) => { this.msgSuccess("修改成功"); this.open = false; this.fileList = []; this.getList(); }); } else { addPreview(this.form).then((response) => { this.msgSuccess("新增成功"); this.open = false; this.fileList = []; this.getList(); }); } } }); },
将数据存储到数据库中。
文件上传效果实现
前端下载按钮点击事件
// 下载 handleDownload(row) { var filePath = row.filePath; var fileName = row.fileName; var url = this.downloadUrl + "?filePath=" + filePath + "&fileName=" + fileName; const a = document.createElement("a"); a.setAttribute("download", fileName); a.setAttribute("target", "_blank"); a.setAttribute("href", url); a.click(); },
获取文件磁盘路径和文件名,并传递参数
后台SpringBoot接口
@GetMapping("download") @apiOperation("下载") public void downloadFile(String filePath,String fileName, HttpServletResponse response) throws IOException { File file = new File(filePath); // 清空response response.reset(); // 设置response的Header 通知浏览器 已下载的方式打开文件 防止文本图片预览 response.addHeader("Content-Disposition", "attachment;filename=" + new String(fileName.getBytes("gbk"), "iso-8859-1")); // 转码之后下载的文件不会出现中文乱码 response.addHeader("Content-Length", "" + file.length()); // 以流的形式下载文件 InputStream fis = new BufferedInputStream(new FileInputStream(filePath)); byte[] buffer = new byte[fis.available()]; fis.read(buffer); fis.close(); OutputStream toClient = new BufferedOutputStream(response.getOutputStream()); toClient.write(buffer); toClient.flush(); toClient.close(); }
文件下载效果
前端点击预览的点击事件
// 预览 handlePreview(row) { var previewServerUrl = row.previewServerUrl; var fileUrl = row.fileUrl; //分别获取预览服务地址和预览参数的地址然后拼接 //预览文件url地址需要使用Base64编码URL let url = previewServerUrl + encodeURIComponent(Base64.encodeURI(fileUrl)); window.open(url); },
注意这里获取预览服务地址和预览参数文件url,这里需要将文件url进行Base64编码
安装依赖
npm install --save js-base64
引入依赖
import { Base64 } from "js-base64";
调用编码方法
Base64.encodeURI(fileUrl)
前端Vue页面完整示例代码
搜索 重置 新增 修改 删除 修改 预览 下载 删除 上传 提示:仅允许导入".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", ".pdf", ".mp3",".mp4",".wav"格式文件!
后台Controller完整代码
package com.ruoyi.web.controller.fzys.basicinfomannager;import com.ruoyi.common.annotation.Log;import com.ruoyi.common.config.RuoYiConfig;import com.ruoyi.common.constant.Constants;import com.ruoyi.common.constant.HttpStatus;import com.ruoyi.common.core.controller.BaseController;import com.ruoyi.common.core.domain.AjaxResult;import com.ruoyi.common.core.domain.fzys.basicinfomanage.BusFilePreview;import com.ruoyi.common.core.page.TableDataInfo;import com.ruoyi.common.enums.BusinessType;import com.ruoyi.common.utils.DateUtils;import com.ruoyi.common.utils.StringUtils;import com.ruoyi.common.utils.UploadUtil;import com.ruoyi.common.utils.poi.ExcelUtil;import com.ruoyi.framework.config.ServerConfig;import com.ruoyi.fzys.service.basicinfomanageService.IBusFilePreviewService;import com.ruoyi.system.utils.FileUtils;import com.ruoyi.web.controller.fzys.config.PreviewConfig;import io.swagger.annotations.ApiOperation;import org.apache.ibatis.annotations.Param;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.*;import org.springframework.web.multipart.MultipartFile;import javax.servlet.http.HttpServletResponse;import java.io.*;import java.util.List;@RestController@RequestMapping("/fzys/basicinfomanage/preview")public class BusFilePreviewController extends BaseController{ private static String[] allowFiles = {".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", ".pdf",".mp3",".mp4",".wav" }; @Autowired private ServerConfig serverConfig; @Autowired private PreviewConfig previewConfig; @Autowired private IBusFilePreviewService busFilePreviewService; @PostMapping("/uploadPreviewFile") public AjaxResult uploadPreviewFile(@Param("file") MultipartFile file) { AjaxResult ajaxResult = AjaxResult.success(); try { String path = RuoYiConfig.getUploadPath() + "/" + DateUtils.datePath() + "/"; FileUtils.check_folder(path); String auth_file_name = UploadUtil.save_file_withAllow(file, path ,allowFiles); if (StringUtils.isEmpty(auth_file_name)){ return AjaxResult.error(HttpStatus.BAD_REQUEST, "文件格式不合法"); } ajaxResult.put("code", 200); ajaxResult.put("message", "成功"); ajaxResult.put("fileName", auth_file_name); ajaxResult.put("filePath", path + auth_file_name); String fileUrl = serverConfig.getUrl()+ Constants.RESOURCE_PREFIX + RuoYiConfig.getUploadPathPre() + File.separator + DateUtils.datePath() + File.separator + auth_file_name; String previewServerUrl = Constants.HTTP + previewConfig.getServerIp() +":" +previewConfig.getServerPort() + Constants.PREVIEW_SERVER_URL; ajaxResult.put("previewServerUrl", previewServerUrl); ajaxResult.put("fileUrl", fileUrl); } catch (IOException e) { ajaxResult.put("code", 400); ajaxResult.put("message", "上传失败"); e.printStackTrace(); } return ajaxResult; } @GetMapping("download") @ApiOperation("下载") public void downloadFile(String filePath,String fileName, HttpServletResponse response) throws IOException { File file = new File(filePath); // 清空response response.reset(); // 设置response的Header 通知浏览器 已下载的方式打开文件 防止文本图片预览 response.addHeader("Content-Disposition", "attachment;filename=" + new String(fileName.getBytes("gbk"), "iso-8859-1")); // 转码之后下载的文件不会出现中文乱码 response.addHeader("Content-Length", "" + file.length()); // 以流的形式下载文件 InputStream fis = new BufferedInputStream(new FileInputStream(filePath)); byte[] buffer = new byte[fis.available()]; fis.read(buffer); fis.close(); OutputStream toClient = new BufferedOutputStream(response.getOutputStream()); toClient.write(buffer); toClient.flush(); toClient.close(); } @GetMapping("/list") public TableDataInfo list(BusFilePreview busFilePreview) { startPage(); List list = busFilePreviewService.selectBusFilePreviewList(busFilePreview); return getDataTable(list); } @Log(title = "preview", businessType = BusinessType.EXPORT) @PostMapping("/export") public void export(HttpServletResponse response, BusFilePreview busFilePreview) throws IOException { List list = busFilePreviewService.selectBusFilePreviewList(busFilePreview); ExcelUtil util = new ExcelUtil(BusFilePreview.class); util.exportExcel(response, list, "preview"); } @GetMapping(value = "/{id}") public AjaxResult getInfo(@PathVariable("id") Long id) { return AjaxResult.success(busFilePreviewService.selectBusFilePreviewById(id)); } @Log(title = "preview", businessType = BusinessType.INSERT) @PostMapping public AjaxResult add(@RequestBody BusFilePreview busFilePreview) throws IOException{ if (StringUtils.isNull(busFilePreview.getFileName())) { AjaxResult.error("缺少文件名称"); } return toAjax(busFilePreviewService.insertBusFilePreview(busFilePreview)); } @Log(title = "preview", businessType = BusinessType.UPDATE) @PutMapping public AjaxResult edit(@RequestBody BusFilePreview busFilePreview) { return toAjax(busFilePreviewService.updateBusFilePreview(busFilePreview)); } @Log(title = "preview", businessType = BusinessType.DELETE) @DeleteMapping("/{ids}") public AjaxResult remove(@PathVariable Long[] ids) { return toAjax(busFilePreviewService.deleteBusFilePreviewByIds(ids)); }}
后台其他各层代码均为根据表结构代码生成。
注意后台需要放开下载接口的鉴权
如果在预览时页面显示
Whitelabel Error Page
找到kkFileView目录下log下kkFileView.log文件查看具体报错
Illegal base64 character 3a
这是因为一开始没将预览文件url进行Base64编码导致。
上传文件时提示
Maximum upload size exceeded:nested exception is java.lang.lllegalStateException:
org.apache.Tomcat.util.http.fileupload.FileSizeLimitExceeededException:
The fiel filed exceeds its maximum perrmitted size of xxx bytes
找到application.yml中修改如下配置
# Spring配置spring: # 资源信息 messages: # 国际化资源文件路径 basename: i18n/messages profiles: active: druid # 文件上传 servlet: multipart: # 单个文件大小 max-file-size: 100MB # 设置总上传的文件大小 max-request-size: 200MB
修改位置
来源地址:https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/128283542
--结束END--
本文标题: SpringBoot+Vue+kkFileView实现文档管理(文档上传、下载、在线预览)
本文链接: https://lsjlt.com/news/414926.html(转载时请注明来源链接)
有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
2024-04-01
2024-04-03
2024-04-03
2024-01-21
2024-01-21
2024-01-21
2024-01-21
2023-12-23
回答
回答
回答
回答
回答
回答
回答
回答
回答
回答
0