SpringBoot+Vue+OpenOffice实现文档管理(文档上传、下载、在线预览)

时间:2023-03-24 21:10:13


场景

SpringBoot集成OpenOffice实现doc文档转html:

SpringBoot集成OpenOffice实现doc文档转html_BADAO_LIUMANG_QIZHI的博客-

在上面初步使用了OpenOffice之后,怎样实现文档管理,文档上传、下载、在线预览等。

首先OpenOffice的下载安装与启动服务参照上文,不再复述。

SpringBoot+Vue+OpenOffice实现文档管理(文档上传、下载、在线预览)

注:

博客:BADAO_LIUMANG_QIZHI的博客_霸道流氓气质_

关注公众号
霸道的程序猿
获取编程相关电子书、教程推送与免费下载。

实现

1、搭建SpringBoot+Vue前后端分离项目

若依前后端分离版本地搭建开发环境并运行项目的教程:

若依前后端分离版手把手教你本地搭建环境并运行项目_BADAO_LIUMANG_QIZHI的博客-

2、设计表

SpringBoot+Vue+OpenOffice实现文档管理(文档上传、下载、在线预览)

数据库语句为

DROP TABLE IF EXISTS `bus_file_preview`;
CREATE TABLE `bus_file_preview`  (
  `id` bigint(0) NOT NULL AUTO_INCREMENT COMMENT '主键',
  `fileName` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '原文件名(上传前文件名)',
  `fileType` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '文件后缀(.xls;.xlsx;.ppt;.doc;.docx;.pptx)',
  `uploadPath` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '上传后文件路径',
  `uploadFileName` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '上传后文件名',
  `pdfPath` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '转换pdf路径',
  `pdfName` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '转换pdf文件名',
  `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 '备注',
  `preview_url` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '预览URL',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 21 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '文件上传与预览' ROW_FORMAT = Dynamic;

SET FOREIGN_KEY_CHECKS = 1;

依照此表生成前后端代码,然后修改代码。

3、文件上传实现

前端按钮

<el-form-item label="附件" prop="photoPath">
          <el-upload
            :headers="headers"
            :action="url"
            :multiple="false"
            :file-list="fileList"
            :on-remove="fileRemove"
            :on-success="uploadSuccess"
            :on-error="uploadError"
            :on-progress="uploadProgress"
            :before-upload="beforeUpload"
            :limit="1"
            :on-exceed="beyond"
            accept=".doc,.docx,.xls,.ppt,.xlsx,.pptx"
          >
            <el-button size="small">
              上传
              <i class="el-icon-upload el-icon--right"></i>
            </el-button>
            <div class="el-upload__tip" style="color: red" slot="tip">
              提示:仅允许导入“.doc、.docx、.xls、.ppt、.xlsx、.pptx”格式文件!
            </div>
          </el-upload>
        </el-form-item>

调用的各方法

// 文件上传失败
    uploadError(err) {
      this.btnLoding = false;
      this.$message.error(res.msg);
    },
    // 上传中
    uploadProgress(e) {
      this.btnLoding = true;
    },
    // 文件上传之前
    beforeUpload(file) {
      console.log(file, "上传之前");
      const fileName = file.name;
      const fileType = fileName.substring(fileName.lastIndexOf("."));
      if (
        fileType === ".doc" ||
        fileType === ".docx" ||
        fileType === ".xls" ||
        fileType === ".ppt" ||
        fileType === ".pptx" ||
        fileType === ".xlsx"
      ) {
        this.form.filename = file.name;
        // 不处理
      } else {
        this.$message.error("请上传正确的文件类型,.doc,.docx,.xls,.ppt,.xlsx,.pptx,");
        return false;
      }
    },
    // 文件上传成功
    uploadSuccess(res, file, fileList) {
      this.form.uploadpath = res.uploadpath;
      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 = [];
    },

对应后台SpingBoot通用上传接口

SpringBoot+Vue+OpenOffice实现文档管理(文档上传、下载、在线预览)

这里做了修改,使其能返回磁盘路径

/**
     * 通用上传请求返回磁盘路径
     */
    @PostMapping("/common/uploadWithAbsolutePath")
    public AjaxResult uploadFileWithAbsolutePath(MultipartFile file) throws Exception
    {
        try
        {
            // 上传文件路径
            String filePath = RuoYiConfig.getUploadPath();
            // 上传并返回新文件名称
            String fileName = FileUploadUtils.uploadWithAbsolutePath(filePath, file);
            AjaxResult ajax = AjaxResult.success();
            ajax.put("uploadpath", filePath+ File.separator+fileName);
            return ajax;
        }
        catch (Exception e)
        {
            return AjaxResult.error(e.getMessage());
        }
    }

调用的方法uploadWithAbsolutePath实现

public static final String uploadWithAbsolutePath(String baseDir, MultipartFile file) throws IOException
    {
        try
        {
            return uploadWithAbsolutePath(baseDir, file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION);
        }
        catch (Exception e)
        {
            throw new IOException(e.getMessage(), e);
        }
    }

其中又调用的uploadWithAbsolutePath方法实现

public static final String uploadWithAbsolutePath(String baseDir, MultipartFile file, String[] allowedExtension)
            throws FileSizeLimitExceededException, IOException, FileNameLengthLimitExceededException,
            InvalidExtensionException
    {
        int fileNamelength = file.getOriginalFilename().length();
        if (fileNamelength > FileUploadUtils.DEFAULT_FILE_NAME_LENGTH)
        {
            throw new FileNameLengthLimitExceededException(FileUploadUtils.DEFAULT_FILE_NAME_LENGTH);
        }
        assertAllowed(file, allowedExtension);
        String fileName = extractFilename(file);
        File desc = getAbsoluteFile(baseDir, fileName);
        file.transferTo(desc);
        return fileName;
    }

其他的若依框架原来的方法。

上传效果

SpringBoot+Vue+OpenOffice实现文档管理(文档上传、下载、在线预览)

4、预览实现

上传之后的文件转换成pdf的实现,在提交按钮时调用后台就接口

/** 提交按钮 */
    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();
            });
          }
        }
      });
    },

首先是新增接口

/**
     * 新增preview
     */

    @Log(title = "preview", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@RequestBody BusFilePreview busFilePreview) throws IOException{
        if (StringUtils.isNull(busFilePreview.getFilename())) {
            AjaxResult.error("缺少文件名称");
        }
        if (StringUtils.isNull(busFilePreview.getUploadpath())) {
            AjaxResult.error("缺少上传文件路径");
        }
        String substringAfter = StringUtils.substringAfter(busFilePreview.getUploadpath(), ".");
        String upName = StringUtils.substringAfterLast(busFilePreview.getUploadpath(), "/");
        busFilePreview.setUploadfilename(upName);
        busFilePreview.setFiletype(substringAfter); //类型
        if ("pdf".equals(substringAfter)){
            FilePdfUtils.copyFile(busFilePreview.getUploadpath(), RuoYiConfig.getProfile());
            String pdfName = StringUtils.substringAfterLast(busFilePreview.getUploadpath(), "/");
            busFilePreview.setPdfpath(RuoYiConfig.getProfile()+ "/" + pdfName);
            busFilePreview.setPdfname(pdfName);
            return  toAjax(busFilePreviewService.insertBusFilePreview(busFilePreview));
        }

        File file = new File(busFilePreview.getUploadpath());
        FileInputStream fileInputStream = new FileInputStream(file);
        String htmFileName = FilePdfUtils.file2pdf(fileInputStream, substringAfter,RuoYiConfig.getProfile());
        String pdfPath = RuoYiConfig.getProfile()+ "/" + htmFileName;
        busFilePreview.setPdfpath(pdfPath);
        String pdfName = StringUtils.substringAfterLast(pdfPath, "/");
        busFilePreview.setPdfname(pdfName);
        String previewUrl = serverConfig.getUrl()+ Constants.RESOURCE_PREFIX+File.separator+htmFileName;
        busFilePreview.setPreviewUrl(previewUrl);
        return toAjax(busFilePreviewService.insertBusFilePreview(busFilePreview));
    }

这里调用了工具类中FilePdfUtils的file2pdf方法,并且将转换后的pdf的路径拼接成静态资源映射后的路径返回给前端。

关于静态资源映射可以参考如下

SpringBoot中通过重写WebMvcConfigurer的方法配置静态资源映射实现图片上传后返回网络Url:

SpringBoot中通过重写WebMvcConfigurer的方法配置静态资源映射实现图片上传后返回网络Url_BADAO_LIUMANG_QIZHI的博客-CSDN博客

5、FilePdfUtils工具类实现

package com.ruoyi.common.utils.pdf;


import com.artofsolving.jodconverter.DocumentConverter;
import com.artofsolving.jodconverter.openoffice.connection.OpenOfficeConnection;
import com.artofsolving.jodconverter.openoffice.connection.SocketOpenOfficeConnection;
import com.artofsolving.jodconverter.openoffice.converter.StreamOpenOfficeDocumentConverter;
import com.ruoyi.common.utils.StringUtils;

import java.io.*;
import java.net.ConnectException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class FilePdfUtils {

    /**
     * 转换文件成pdf
     *
     * @param fromFileInputStream:
     * @throws IOException
     */
    public static String file2pdf(InputStream fromFileInputStream, String type,String pdfPath) throws IOException {
        Date date = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
        String timesuffix = sdf.format(date);
        String docFileName = null;
        String htmFileName = null;
        if("doc".equals(type)){
            docFileName = "doc_" + timesuffix + ".doc";
            htmFileName = "doc_" + timesuffix + ".pdf";
        }else if("docx".equals(type)){
            docFileName = "docx_" + timesuffix + ".docx";
            htmFileName = "docx_" + timesuffix + ".pdf";
        }else if("xls".equals(type)){
            docFileName = "xls_" + timesuffix + ".xls";
            htmFileName = "xls_" + timesuffix + ".pdf";
        }else if("ppt".equals(type)){
            docFileName = "ppt_" + timesuffix + ".ppt";
            htmFileName = "ppt_" + timesuffix + ".pdf";
        }else if("xlsx".equals(type)){
            docFileName = "xlsx_" + timesuffix + ".xlsx";
            htmFileName = "xlsx_" + timesuffix + ".pdf";
        }else if("pptx".equals(type)){
            docFileName = "pptx_" + timesuffix + ".pptx";
            htmFileName = "pptx_" + timesuffix + ".pdf";
        }else{
            return null;
        }


        check_folder(pdfPath);

        File htmlOutputFile = new File(pdfPath + File.separatorChar + htmFileName);
        File docInputFile = new File(pdfPath + File.separatorChar + docFileName);
        if (htmlOutputFile.exists())
            htmlOutputFile.delete();
        htmlOutputFile.createNewFile();
        if (docInputFile.exists())
            docInputFile.delete();
        docInputFile.createNewFile();
        /**
         * 由fromFileInputStream构建输入文件
         */
        try {
            OutputStream os = new FileOutputStream(docInputFile);
            int bytesRead = 0;
            byte[] buffer = new byte[1024 * 8];
            while ((bytesRead = fromFileInputStream.read(buffer)) != -1) {
                os.write(buffer, 0, bytesRead);
            }

            os.close();
            fromFileInputStream.close();
        } catch (IOException e) {
        }

        OpenOfficeConnection connection = new SocketOpenOfficeConnection(8100);
        try {
            connection.connect();
        } catch (ConnectException e) {
            System.err.println("文件转换出错,请检查OpenOffice服务是否启动。");
        }

        DocumentConverter converter = new StreamOpenOfficeDocumentConverter(connection);
        converter.convert(docInputFile, htmlOutputFile);
        connection.disconnect();
        // 转换完之后删除word文件
        docInputFile.delete();
        System.out.println(htmFileName);
        return htmFileName;
    }

    public static void check_folder(String path) {
        File dir = new File(path);
        // 判断文件夹是否存在
        if (dir.isDirectory()) {
        } else {
            dir.mkdirs();
        }
    }

    public static void copyFile(String oldPath, String newPath) throws IOException {
        File oldFile = new File(oldPath);//获取旧的文件File对象
        File file = new File(newPath + oldFile.separator + StringUtils.substringAfterLast(oldPath, "/"));  //获取新的文件File对象并生成文件
        FileInputStream in = new FileInputStream(oldFile);  //
        FileOutputStream out = new FileOutputStream(file);

        byte[] buffer=new byte[2097152];
        int readByte = 0;
        //读取旧文件的流写入新文件里
        while((readByte = in.read(buffer)) != -1){
            out.write(buffer, 0, readByte);
        }

        in.close();
        out.close();
    }

}

注意这里的连接openOffice的服务的端口要对应并且确保openOffice已经启动

SpringBoot+Vue+OpenOffice实现文档管理(文档上传、下载、在线预览)

 然后工具类FilePdfUtils是在common模块下,所以后台需要在此模块下pom文件中添加依赖

<dependency>
            <groupId>com.artofsolving</groupId>
            <artifactId>jodconverter</artifactId>
            <version>2.2.1</version>
        </dependency>

添加位置

SpringBoot+Vue+OpenOffice实现文档管理(文档上传、下载、在线预览)

注意这里的版本为2.2.1,Maven*仓库中此为最高版本

SpringBoot+Vue+OpenOffice实现文档管理(文档上传、下载、在线预览)

这里在调用工具类转换文件时,如果文件类型为docx、pptx、xlsx时会报错提示

unknown document format for file ....docx

SpringBoot+Vue+OpenOffice实现文档管理(文档上传、下载、在线预览)

这是因为2.2.1的能转换doc ,但2.2.2才能转换docx,如果你用2.2.1的jar包,转换2.2.2的docx文档就会出错

除了不加载Maven*仓库的2.1的依赖之外,还可以重写DocumentFormatRegistry接口的getFormatByFileExtension方法

SpringBoot+Vue+OpenOffice实现文档管理(文档上传、下载、在线预览)

注意包名一致

package com.artofsolving.jodconverter;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * @ClassName: online
 * @description: 重写 BasicDocumentFormatRegistry 文档格式
 * @Author: yandongfa
 * @Data: 2020-03-24 19:47
 * @Version: 1.0
 **/
public class BasicDocumentFormatRegistry implements DocumentFormatRegistry {

    private List/* <DocumentFormat> */ documentFormats = new ArrayList();

    public void addDocumentFormat(DocumentFormat documentFormat) {
        documentFormats.add(documentFormat);
    }

    protected List/* <DocumentFormat> */ getDocumentFormats() {
        return documentFormats;
    }

    /**
     * @param extension
     *            the file extension
     * @return the DocumentFormat for this extension, or null if the extension
     *         is not mapped
     */
    public DocumentFormat getFormatByFileExtension(String extension) {
        if (extension == null) {
            return null;
        }

        //new DefaultDocumentFormatRegistry();
        //将文件名后缀统一转化
        if (extension.indexOf("doc") >= 0) {
            extension = "doc";
        }
        if (extension.indexOf("ppt") >= 0) {
            extension = "ppt";
        }
        if (extension.indexOf("xls") >= 0) {
            extension = "xls";
        }
        String lowerExtension = extension.toLowerCase();
        for (Iterator it = documentFormats.iterator(); it.hasNext();) {
            DocumentFormat format = (DocumentFormat) it.next();
            if (format.getFileExtension().equals(lowerExtension)) {
                return format;
            }
        }
        return null;
    }

    public DocumentFormat getFormatByMimeType(String mimeType) {
        for (Iterator it = documentFormats.iterator(); it.hasNext();) {
            DocumentFormat format = (DocumentFormat) it.next();
            if (format.getMimeType().equals(mimeType)) {
                return format;
            }
        }
        return null;
    }
}

6、在线预览实现

<el-button
            size="mini"
            type="text"
            icon="el-icon-edit"
            @click="handlePreview(scope.row)"
            >预览</el-button
          >

调用js方法

// 预览
    handlePreview(row) {
      let url = row.previewUrl;
      window.open(url);
    },

这里直接打开url这个字段对应的地址即可,url是在进行文件转换成pdf时生成的映射的服务器上的url

String previewUrl = serverConfig.getUrl()+ Constants.RESOURCE_PREFIX+File.separator+htmFileName;

注意这里的预览地址如果有拦截,让在后台配置中放开白名单。

SpringBoot+Vue+OpenOffice实现文档管理(文档上传、下载、在线预览)

7、文件下载实现

// 下载
    handleDownload(row) {
      const baseURL = process.env.VUE_APP_BASE_API
      window.location.href = baseURL + "/common/download/resourceeasy?resource=" + encodeURI(row.uploadpath);
    },

这里直接修改后台的下载本地资源的通用下载方法

@GetMapping("/common/download/resourceeasy")
    public void resourceDownloadEasy(String resource, HttpServletRequest request, HttpServletResponse response)
            throws Exception
    {
        try
        {
            if (!FileUtils.checkAllowDownload(resource))
            {
                throw new Exception(StringUtils.format("资源文件({})非法,不允许下载。 ", resource));
            }
            response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
            FileUtils.setAttachmentResponseHeader(response, resource);
            FileUtils.writeBytes(resource, response.getOutputStream());
        }
        catch (Exception e)
        {
            log.error("下载文件失败", e);
        }
    }

下载效果

SpringBoot+Vue+OpenOffice实现文档管理(文档上传、下载、在线预览)

8、各层完整代码

前端完整代码

<template>
  <div class="app-container">
    <el-form
      :model="queryParams"
      ref="queryForm"
      :inline="true"
      v-show="showSearch"
      label-width="68px"
    >
      <el-form-item label="原文件名" prop="filename">
        <el-input
          v-model="queryParams.filename"
          placeholder="请输入原文件名"
          clearable
          size="small"
          @keyup.enter.native="handleQuery"
        />
      </el-form-item>

      <el-form-item>
        <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery"
          >搜索</el-button
        >
        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
      </el-form-item>
    </el-form>

    <el-row :gutter="10" class="mb8">
      <el-col :span="1.5">
        <el-button
          type="primary"
          icon="el-icon-plus"
          size="mini"
          @click="handleAdd"
          v-hasPermi="['basicinfomanage:preview:add']"
          >新增</el-button
        >
      </el-col>
      <el-col :span="1.5">
        <el-button
          type="success"
          icon="el-icon-edit"
          size="mini"
          :disabled="single"
          @click="handleUpdate"
          v-hasPermi="['basicinfomanage:preview:edit']"
          >修改</el-button
        >
      </el-col>
      <el-col :span="1.5">
        <el-button
          type="danger"
          icon="el-icon-delete"
          size="mini"
          :disabled="multiple"
          @click="handleDelete"
          v-hasPermi="['basicinfomanage:preview:remove']"
          >删除</el-button
        >
      </el-col>

      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
    </el-row>

    <el-table
      v-loading="loading"
      :data="previewList"
      @selection-change="handleSelectionChange"
    >
      <el-table-column type="selection" width="55" align="center" />
      <el-table-column
        show-overflow-tooltip
        label="文件名"
        align="center"
        prop="filename"
      />
      <el-table-column
        show-overflow-tooltip
        label="上传后文件路径"
        align="center"
        prop="uploadpath"
      />
      <el-table-column
        show-overflow-tooltip
        label="转换pdf路径"
        align="center"
        prop="pdfpath"
        width="400"
      />
       <el-table-column
        show-overflow-tooltip
        label="预览地址"
        align="center"
        prop="previewUrl"
        width="400"
      />
      <el-table-column show-overflow-tooltip label="备注" align="center" prop="remark" />
      <el-table-column
        label="操作"
        align="center"
        class-name="small-padding fixed-width"
        width="200"
      >
        <template slot-scope="scope">
          <el-button
            size="mini"
            type="text"
            icon="el-icon-edit"
            @click="handleUpdate(scope.row)"
            v-hasPermi="['basicinfomanage:preview:edit']"
            >修改</el-button
          >
          <el-button
            size="mini"
            type="text"
            icon="el-icon-edit"
            @click="handlePreview(scope.row)"
            >预览</el-button
          >
          <el-button
            size="mini"
            type="text"
            icon="el-icon-edit"
            @click="handleDownload(scope.row)"
            >下载</el-button
          >
          <el-button
            size="mini"
            type="text"
            icon="el-icon-delete"
            @click="handleDelete(scope.row)"
            v-hasPermi="['basicinfomanage:preview:remove']"
            >删除</el-button
          >
        </template>
      </el-table-column>
    </el-table>

    <pagination
      v-show="total > 0"
      :total="total"
      :page.sync="queryParams.pageNum"
      :limit.sync="queryParams.pageSize"
      @pagination="getList"
    />

    <!-- 添加或修改preview对话框 -->
    <el-dialog :title="title" :visible.sync="open" width="35%" append-to-body>
      <el-form ref="form" :model="form" :rules="rules" label-width="110px">
        <el-form-item label="文件名" prop="filename">
          <el-input v-model="form.filename" placeholder="请输入文件名" disabled />
        </el-form-item>
        <el-form-item label="上传后文件路径" prop="uploadpath">
          <el-input v-model="form.uploadpath" placeholder="请输入上传后文件名" disabled />
        </el-form-item>
        <el-form-item label="备注" prop="remark">
          <el-input v-model="form.remark" placeholder="请输入备注"  />
        </el-form-item>
        <el-form-item label="附件" prop="photoPath">
          <el-upload
            :headers="headers"
            :action="url"
            :multiple="false"
            :file-list="fileList"
            :on-remove="fileRemove"
            :on-success="uploadSuccess"
            :on-error="uploadError"
            :on-progress="uploadProgress"
            :before-upload="beforeUpload"
            :limit="1"
            :on-exceed="beyond"
            accept=".doc,.docx,.xls,.ppt,.xlsx,.pptx"
          >
            <el-button size="small">
              上传
              <i class="el-icon-upload el-icon--right"></i>
            </el-button>
            <div class="el-upload__tip" style="color: red" slot="tip">
              提示:仅允许导入“.doc、.docx、.xls、.ppt、.xlsx、.pptx”格式文件!
            </div>
          </el-upload>
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button type="primary" @click="submitForm">确 定</el-button>
        <el-button @click="cancel">取 消</el-button>
      </div>
    </el-dialog>
  </div>
</template>

<script>
import {
  listPreview,
  getPreview,
  delPreview,
  addPreview,
  updatePreview,
} from "@/api/system/preview";
import { getToken } from "@/utils/auth";

export default {
  name: "preview",
  data() {
    return {
      // 遮罩层
      loading: true,
      // 选中数组
      ids: [],
      // 非单个禁用
      single: true,
      // 非多个禁用
      multiple: true,
      // 显示搜索条件
      showSearch: true,
      // 总条数
      total: 0,
      // preview表格数据
      previewList: [],
      // 弹出层标题
      title: "",
      // 是否显示弹出层
      open: false,
      // 查询参数
      queryParams: {
        pageNum: 1,
        pageSize: 10,
        filename: null,
        filetype: null,
        uploadpath: null,
        pdfpath: null,
        pdfname: null,
      },
      // 表单参数
      form: {},
      // 表单校验
      rules: {
        filename: [
          {
            required: true,
            message: "文件名称不能为空",
            trigger: "blur",
          },
        ],
      },
      // 上传按钮闸口
      btnLoding: false,
      //  请求头
      headers: { Authorization: "Bearer" + " " + getToken() },
      // 上传地址
      url: process.env.VUE_APP_BASE_API + "/common/uploadWithAbsolutePath",
      // 图片列表
      fileList: [],
    };
  },
  created() {
    this.getList();
  },
  methods: {
    /** 查询preview列表 */
    getList() {
      this.loading = true;
      listPreview(this.queryParams).then((response) => {
        this.previewList = response.rows;
        this.total = response.total;
        this.loading = false;
      });
    },
    // 取消按钮
    cancel() {
      this.open = false;
      this.reset();
    },
    // 表单重置
    reset() {
      this.form = {
        id: null,
        filename: null,
        uploadpath: null,
      };
      this.resetForm("form");
    },
    /** 搜索按钮操作 */
    handleQuery() {
      this.queryParams.pageNum = 1;
      this.getList();
    },
    /** 重置按钮操作 */
    resetQuery() {
      this.resetForm("queryForm");
      this.handleQuery();
    },
    // 多选框选中数据
    handleSelectionChange(selection) {
      this.ids = selection.map((item) => item.id);
      this.single = selection.length !== 1;
      this.multiple = !selection.length;
    },
    /** 新增按钮操作 */
    handleAdd() {
      this.fileRemove();
      this.open = true;
      this.title = "添加文件";
    },
    /** 修改按钮操作 */
    handleUpdate(row) {
      this.reset();
      const id = row.id || this.ids;
      getPreview(id).then((response) => {
        this.form = response.data;
        this.open = true;
        this.title = "修改文件";
      });
    },
    // 预览
    handlePreview(row) {
      let url = row.previewUrl;
      window.open(url);
    },
    // 下载
    handleDownload(row) {
      const baseURL = process.env.VUE_APP_BASE_API
      window.location.href = baseURL + "/common/download/resourceeasy?resource=" + encodeURI(row.uploadpath);
    },

    /** 提交按钮 */
    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();
            });
          }
        }
      });
    },
    /** 删除按钮操作 */
    handleDelete(row) {
      const ids = row.id || this.ids;
      this.$confirm('是否确认删除文件编号为"' + ids + '"的数据项?', "警告", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      })
        .then(function () {
          return delPreview(ids);
        })
        .then(() => {
          this.getList();
          this.msgSuccess("删除成功");
        });
    },
    // 文件上传失败
    uploadError(err) {
      this.btnLoding = false;
      this.$message.error(res.msg);
    },
    // 上传中
    uploadProgress(e) {
      this.btnLoding = true;
    },
    // 文件上传之前
    beforeUpload(file) {
      console.log(file, "上传之前");
      const fileName = file.name;
      const fileType = fileName.substring(fileName.lastIndexOf("."));
      if (
        fileType === ".doc" ||
        fileType === ".docx" ||
        fileType === ".xls" ||
        fileType === ".ppt" ||
        fileType === ".pptx" ||
        fileType === ".xlsx"
      ) {
        this.form.filename = file.name;
        // 不处理
      } else {
        this.$message.error("请上传正确的文件类型,.doc,.docx,.xls,.ppt,.xlsx,.pptx,");
        return false;
      }
    },
    // 文件上传成功
    uploadSuccess(res, file, fileList) {
      this.form.uploadpath = res.uploadpath;
      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 = [];
    },
  },
};
</script>

前端js代码

import request from '@/utils/request'


// 查询preview列表
export function listPreview(query) {
  return request({
    url: '/system/preview/list',
    method: 'get',
    params: query
  })
}

// 查询preview详细
export function getPreview(id) {
  return request({
    url: '/system/preview/' + id,
    method: 'get'
  })
}

// 新增preview
export function addPreview(data) {
  return request({
    url: '/system/preview',
    method: 'post',
    data: data
  })
}

// 修改preview
export function updatePreview(data) {
  return request({
    url: '/system/preview',
    method: 'put',
    data: data
  })
}

// 删除preview
export function delPreview(id) {
  return request({
    url: '/system/preview/' + id,
    method: 'delete'
  })
}

后台实体类

package com.ruoyi.system.domain;

import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.BaseEntity;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;

public class BusFilePreview extends BaseEntity
{
    private static final long serialVersionUID = 1L;

    /** 主键 */
    private Long id;

    /** 原文件名(上传前文件名) */
    @Excel(name = "原文件名", readConverterExp = "上传前文件名")
    private String filename;

    /** 文件后缀(.xls;.xlsx;.ppt;.doc;.docx;.pptx) */
    @Excel(name = "文件后缀", readConverterExp = ".=xls;.xlsx;.ppt;.doc;.docx;.pptx")
    private String filetype;

    /** 上传后文件路径 */
    @Excel(name = "上传后文件路径")
    private String uploadpath;

    /** 上传后文件名 */
    @Excel(name = "上传后文件名")
    private String uploadfilename;

    /** 转换pdf路径 */
    @Excel(name = "转换pdf路径")
    private String pdfpath;

    /** 转换pdf文件名 */
    @Excel(name = "转换pdf文件名")
    private String pdfname;

    /** 预览地址 */
    @Excel(name = "预览地址")
    private String previewUrl;

    public String getPreviewUrl() {
        return previewUrl;
    }

    public void setPreviewUrl(String previewUrl) {
        this.previewUrl = previewUrl;
    }

    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 setFiletype(String filetype)
    {
        this.filetype = filetype;
    }

    public String getFiletype()
    {
        return filetype;
    }
    public void setUploadpath(String uploadpath)
    {
        this.uploadpath = uploadpath;
    }

    public String getUploadpath()
    {
        return uploadpath;
    }
    public void setUploadfilename(String uploadfilename)
    {
        this.uploadfilename = uploadfilename;
    }

    public String getUploadfilename()
    {
        return uploadfilename;
    }
    public void setPdfpath(String pdfpath)
    {
        this.pdfpath = pdfpath;
    }

    public String getPdfpath()
    {
        return pdfpath;
    }
    public void setPdfname(String pdfname)
    {
        this.pdfname = pdfname;
    }

    public String getPdfname()
    {
        return pdfname;
    }

    @Override
    public String toString() {
        return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
                .append("id", getId())
                .append("filename", getFilename())
                .append("filetype", getFiletype())
                .append("uploadpath", getUploadpath())
                .append("uploadfilename", getUploadfilename())
                .append("pdfpath", getPdfpath())
                .append("pdfname", getPdfname())
                .append("createTime", getCreateTime())
                .append("createBy", getCreateBy())
                .append("updateTime", getUpdateTime())
                .append("updateBy", getUpdateBy())
                .append("remark", getRemark())
                .toString();
    }
}

后台mapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.system.mapper.BusFilePreviewMapper">

    <resultMap type="BusFilePreview" >
        <result property="id"    column="id"    />
        <result property="filename"    column="fileName"    />
        <result property="filetype"    column="fileType"    />
        <result property="uploadpath"    column="uploadPath"    />
        <result property="uploadfilename"    column="uploadFileName"    />
        <result property="pdfpath"    column="pdfPath"    />
        <result property="pdfname"    column="pdfName"    />
        <result property="createTime"    column="create_time"    />
        <result property="createBy"    column="create_by"    />
        <result property="updateTime"    column="update_time"    />
        <result property="updateBy"    column="update_by"    />
        <result property="remark"    column="remark"    />
        <result property="previewUrl"    column="preview_url"    />
    </resultMap>

    <sql >
        select id, fileName, fileType, uploadPath, uploadFileName, pdfPath, pdfName, create_time, create_by, update_time, update_by, remark ,preview_url from bus_file_preview
    </sql>

    <select  parameterType="BusFilePreview" resultMap="BusFilePreviewResult">
        <include ref/>
        <where>
            <if test="filename != null  and filename != ''"> and fileName like concat('%', #{filename}, '%')</if>
            <if test="filetype != null  and filetype != ''"> and fileType = #{filetype}</if>
            <if test="uploadpath != null  and uploadpath != ''"> and uploadPath = #{uploadpath}</if>
            <if test="uploadfilename != null  and uploadfilename != ''"> and uploadFileName like concat('%', #{uploadfilename}, '%')</if>
            <if test="pdfpath != null  and pdfpath != ''"> and pdfPath = #{pdfpath}</if>
            <if test="pdfname != null  and pdfname != ''"> and pdfName like concat('%', #{pdfname}, '%')</if>
        </where>
    </select>

    <select  parameterType="Long" resultMap="BusFilePreviewResult">
        <include ref/>
        where id = #{id}
    </select>

    <insert  parameterType="BusFilePreview" useGeneratedKeys="true" keyProperty="id">
        insert into bus_file_preview
        <trim prefix="(" suffix=")" suffixOverrides=",">
            <if test="filename != null">fileName,</if>
            <if test="filetype != null">fileType,</if>
            <if test="uploadpath != null">uploadPath,</if>
            <if test="uploadfilename != null">uploadFileName,</if>
            <if test="pdfpath != null">pdfPath,</if>
            <if test="pdfname != null">pdfName,</if>
            <if test="createTime != null">create_time,</if>
            <if test="createBy != null">create_by,</if>
            <if test="updateTime != null">update_time,</if>
            <if test="updateBy != null">update_by,</if>
            <if test="remark != null">remark,</if>
            <if test="previewUrl != null">preview_url,</if>

         </trim>
        <trim prefix="values (" suffix=")" suffixOverrides=",">
            <if test="filename != null">#{filename},</if>
            <if test="filetype != null">#{filetype},</if>
            <if test="uploadpath != null">#{uploadpath},</if>
            <if test="uploadfilename != null">#{uploadfilename},</if>
            <if test="pdfpath != null">#{pdfpath},</if>
            <if test="pdfname != null">#{pdfname},</if>
            <if test="createTime != null">#{createTime},</if>
            <if test="createBy != null">#{createBy},</if>
            <if test="updateTime != null">#{updateTime},</if>
            <if test="updateBy != null">#{updateBy},</if>
            <if test="remark != null">#{remark},</if>
            <if test="previewUrl != null">#{previewUrl},</if>
         </trim>
    </insert>

    <update  parameterType="BusFilePreview">
        update bus_file_preview
        <trim prefix="SET" suffixOverrides=",">
            <if test="filename != null">fileName = #{filename},</if>
            <if test="filetype != null">fileType = #{filetype},</if>
            <if test="uploadpath != null">uploadPath = #{uploadpath},</if>
            <if test="uploadfilename != null">uploadFileName = #{uploadfilename},</if>
            <if test="pdfpath != null">pdfPath = #{pdfpath},</if>
            <if test="pdfname != null">pdfName = #{pdfname},</if>
            <if test="createTime != null">create_time = #{createTime},</if>
            <if test="createBy != null">create_by = #{createBy},</if>
            <if test="updateTime != null">update_time = #{updateTime},</if>
            <if test="updateBy != null">update_by = #{updateBy},</if>
            <if test="remark != null">remark = #{remark},</if>
            <if test="previewUrl != null">preview_url = #{previewUrl},</if>
        </trim>
        where id = #{id}
    </update>

    <delete  parameterType="Long">
        delete from bus_file_preview where id = #{id}
    </delete>

    <delete  parameterType="String">
        delete from bus_file_preview where id in
        <foreach item="id" collection="array" open="(" separator="," close=")">
            #{id}
        </foreach>
    </delete>

</mapper>

后台mapper接口

package com.ruoyi.system.mapper;



import com.ruoyi.system.domain.BusFilePreview;

import java.util.List;

/**
 * previewMapper接口
 *
 * @author ruoyi
 * @date 2021-10-29
 */
public interface BusFilePreviewMapper
{
    /**
     * 查询preview
     *
     * @param id previewID
     * @return preview
     */
    public BusFilePreview selectBusFilePreviewById(Long id);

    /**
     * 查询preview列表
     *
     * @param busFilePreview preview
     * @return preview集合
     */
    public List<BusFilePreview> selectBusFilePreviewList(BusFilePreview busFilePreview);

    /**
     * 新增preview
     *
     * @param busFilePreview preview
     * @return 结果
     */
    public int insertBusFilePreview(BusFilePreview busFilePreview);

    /**
     * 修改preview
     *
     * @param busFilePreview preview
     * @return 结果
     */
    public int updateBusFilePreview(BusFilePreview busFilePreview);

    /**
     * 删除preview
     *
     * @param id previewID
     * @return 结果
     */
    public int deleteBusFilePreviewById(Long id);

    /**
     * 批量删除preview
     *
     * @param ids 需要删除的数据ID
     * @return 结果
     */
    public int deleteBusFilePreviewByIds(Long[] ids);
}

后台service接口

package com.ruoyi.system.service;


import com.ruoyi.system.domain.BusFilePreview;

import java.util.List;

/**
 * previewService接口
 *
 * @author ruoyi
 * @date 2021-10-29
 */
public interface IBusFilePreviewService
{
    /**
     * 查询preview
     *
     * @param id previewID
     * @return preview
     */
    public BusFilePreview selectBusFilePreviewById(Long id);

    /**
     * 查询preview列表
     *
     * @param busFilePreview preview
     * @return preview集合
     */
    public List<BusFilePreview> selectBusFilePreviewList(BusFilePreview busFilePreview);

    /**
     * 新增preview
     *
     * @param busFilePreview preview
     * @return 结果
     */
    public int insertBusFilePreview(BusFilePreview busFilePreview);

    /**
     * 修改preview
     *
     * @param busFilePreview preview
     * @return 结果
     */
    public int updateBusFilePreview(BusFilePreview busFilePreview);

    /**
     * 批量删除preview
     *
     * @param ids 需要删除的previewID
     * @return 结果
     */
    public int deleteBusFilePreviewByIds(Long[] ids);

    /**
     * 删除preview信息
     *
     * @param id previewID
     * @return 结果
     */
    public int deleteBusFilePreviewById(Long id);
}

后台serviceImpl

package com.ruoyi.system.service.impl;


import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.system.domain.BusFilePreview;
import com.ruoyi.system.mapper.BusFilePreviewMapper;
import com.ruoyi.system.service.IBusFilePreviewService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * previewService业务层处理
 *
 * @author ruoyi
 * @date 2021-10-29
 */
@Service
public class BusFilePreviewServiceImpl implements IBusFilePreviewService
{
    @Autowired
    private BusFilePreviewMapper busFilePreviewMapper;

    /**
     * 查询preview
     *
     * @param id previewID
     * @return preview
     */
    @Override
    public BusFilePreview selectBusFilePreviewById(Long id)
    {
        return busFilePreviewMapper.selectBusFilePreviewById(id);
    }

    /**
     * 查询preview列表
     *
     * @param busFilePreview preview
     * @return preview
     */
    @Override
    public List<BusFilePreview> selectBusFilePreviewList(BusFilePreview busFilePreview)
    {
        return busFilePreviewMapper.selectBusFilePreviewList(busFilePreview);
    }

    /**
     * 新增preview
     *
     * @param busFilePreview preview
     * @return 结果
     */
    @Override
    public int insertBusFilePreview(BusFilePreview busFilePreview)
    {
        busFilePreview.setCreateTime(DateUtils.getNowDate());
        busFilePreview.setCreateBy(String.valueOf(SecurityUtils.getUsername()));// 创建人
        return busFilePreviewMapper.insertBusFilePreview(busFilePreview);
    }

    /**
     * 修改preview
     *
     * @param busFilePreview preview
     * @return 结果
     */
    @Override
    public int updateBusFilePreview(BusFilePreview busFilePreview)
    {
        busFilePreview.setUpdateTime(DateUtils.getNowDate());
        busFilePreview.setUpdateBy(String.valueOf(SecurityUtils.getUsername()));// 创建人
        return busFilePreviewMapper.updateBusFilePreview(busFilePreview);
    }

    /**
     * 批量删除preview
     *
     * @param ids 需要删除的previewID
     * @return 结果
     */
    @Override
    public int deleteBusFilePreviewByIds(Long[] ids)
    {
        return busFilePreviewMapper.deleteBusFilePreviewByIds(ids);
    }

    /**
     * 删除preview信息
     *
     * @param id previewID
     * @return 结果
     */
    @Override
    public int deleteBusFilePreviewById(Long id)
    {
        return busFilePreviewMapper.deleteBusFilePreviewById(id);
    }
}

后台Controller

package com.ruoyi.web.controller.system;

import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.pdf.FilePdfUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.framework.config.ServerConfig;
import com.ruoyi.system.domain.BusFilePreview;
import com.ruoyi.system.service.IBusFilePreviewService;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.List;

/**
 * previewController
 *
 * @author ruoyi
 * @date 2021-10-29
 */
@RestController
@RequestMapping("/system/preview")
public class BusFilePreviewController extends BaseController
{
    @Autowired
    private IBusFilePreviewService busFilePreviewService;

    @Autowired
    private ServerConfig serverConfig;

    /**
     * 查询preview列表
     */
    @GetMapping("/list")
    public TableDataInfo list(BusFilePreview busFilePreview)
    {
        startPage();
        List<BusFilePreview> list = busFilePreviewService.selectBusFilePreviewList(busFilePreview);
        return getDataTable(list);
    }

    /**
     * 获取preview详细信息
     */

    @GetMapping(value = "/{id}")
    public AjaxResult getInfo(@PathVariable("id") Long id)
    {
        return AjaxResult.success(busFilePreviewService.selectBusFilePreviewById(id));
    }

    /**
     * 新增preview
     */

    @Log(title = "preview", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@RequestBody BusFilePreview busFilePreview) throws IOException{
        if (StringUtils.isNull(busFilePreview.getFilename())) {
            AjaxResult.error("缺少文件名称");
        }
        if (StringUtils.isNull(busFilePreview.getUploadpath())) {
            AjaxResult.error("缺少上传文件路径");
        }
        String substringAfter = StringUtils.substringAfter(busFilePreview.getUploadpath(), ".");
        String upName = StringUtils.substringAfterLast(busFilePreview.getUploadpath(), "/");
        busFilePreview.setUploadfilename(upName);
        busFilePreview.setFiletype(substringAfter); //类型
        if ("pdf".equals(substringAfter)){
            FilePdfUtils.copyFile(busFilePreview.getUploadpath(), RuoYiConfig.getProfile());
            String pdfName = StringUtils.substringAfterLast(busFilePreview.getUploadpath(), "/");
            busFilePreview.setPdfpath(RuoYiConfig.getProfile()+ "/" + pdfName);
            busFilePreview.setPdfname(pdfName);
            return  toAjax(busFilePreviewService.insertBusFilePreview(busFilePreview));
        }

        File file = new File(busFilePreview.getUploadpath());
        FileInputStream fileInputStream = new FileInputStream(file);
        String htmFileName = FilePdfUtils.file2pdf(fileInputStream, substringAfter,RuoYiConfig.getProfile());
        String pdfPath = RuoYiConfig.getProfile()+ "/" + htmFileName;
        busFilePreview.setPdfpath(pdfPath);
        String pdfName = StringUtils.substringAfterLast(pdfPath, "/");
        busFilePreview.setPdfname(pdfName);
        String previewUrl = serverConfig.getUrl()+ Constants.RESOURCE_PREFIX+File.separator+htmFileName;
        busFilePreview.setPreviewUrl(previewUrl);
        return toAjax(busFilePreviewService.insertBusFilePreview(busFilePreview));
    }

    /**
     * 修改preview
     */
    @Log(title = "preview", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@RequestBody BusFilePreview busFilePreview) throws IOException {
        if (StringUtils.isNull(busFilePreview.getFilename())) {
            AjaxResult.error("缺少文件名称");
        }
        if (StringUtils.isNull(busFilePreview.getUploadpath())) {
            AjaxResult.error("缺少上传文件路径");
        }
        String substringAfter = StringUtils.substringAfter(busFilePreview.getUploadpath(), ".");
        String upName = StringUtils.substringAfterLast(busFilePreview.getUploadpath(), "/");
        busFilePreview.setUploadfilename(upName);
        busFilePreview.setFiletype(substringAfter); //类型
        if ("pdf".equals(substringAfter)){
            FilePdfUtils.copyFile(busFilePreview.getUploadpath(), RuoYiConfig.getProfile());
            String pdfName = StringUtils.substringAfterLast(busFilePreview.getUploadpath(), "/");
            busFilePreview.setPdfpath(RuoYiConfig.getProfile()+ "/" + pdfName);
            busFilePreview.setPdfname(pdfName);
            return  toAjax(busFilePreviewService.insertBusFilePreview(busFilePreview));
        }

        File file = new File(busFilePreview.getUploadpath());
        FileInputStream fileInputStream = new FileInputStream(file);
        String htmFileName = FilePdfUtils.file2pdf(fileInputStream, substringAfter,RuoYiConfig.getProfile());
        String pdfPath = RuoYiConfig.getProfile()+ "/" + htmFileName;
        busFilePreview.setPdfpath(pdfPath);
        String pdfName = StringUtils.substringAfterLast(pdfPath, "/");
        busFilePreview.setPdfname(pdfName);
        String previewUrl = serverConfig.getUrl()+ Constants.RESOURCE_PREFIX+File.separator+htmFileName;
        busFilePreview.setPreviewUrl(previewUrl);
        return toAjax(busFilePreviewService.updateBusFilePreview(busFilePreview));
    }

    /**
     * 删除preview
     */
    @Log(title = "preview", businessType = BusinessType.DELETE)
 @DeleteMapping("/{ids}")
    public AjaxResult remove(@PathVariable Long[] ids)
    {
        return toAjax(busFilePreviewService.deleteBusFilePreviewByIds(ids));
    }

    @GetMapping("/pdf")
    @ApiOperation(value = "预览")
    public void prePDF(Long id, HttpServletRequest request, HttpServletResponse response) throws IOException {
        BusFilePreview busFilePreview = busFilePreviewService.selectBusFilePreviewById(id);
        if (StringUtils.isNotNull(busFilePreview) && StringUtils.isNotNull(busFilePreview.getPdfpath())) {
            File file = new File(busFilePreview.getPdfpath());
            if (file.exists()) {
                byte[] data = null;
                try {
                    FileInputStream input = new FileInputStream(file);
                    data = new byte[input.available()];
                    input.read(data);
                    response.getOutputStream().write(data);
                    input.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            } else if (!file.exists()){
                BusFilePreview filePreview = new BusFilePreview();
                filePreview.setId(id);
                filePreview.setRemark("文件不存在");
                busFilePreviewService.updateBusFilePreview(filePreview);
            }
        }
    }
}

后台通用Controller

package com.ruoyi.web.controller.common;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.file.FileUploadUtils;
import com.ruoyi.common.utils.file.FileUtils;
import com.ruoyi.framework.config.ServerConfig;

import java.io.File;

/**
 * 通用请求处理
 *
 * @author ruoyi
 */
@RestController
public class CommonController
{
    private static final Logger log = LoggerFactory.getLogger(CommonController.class);

    @Autowired
    private ServerConfig serverConfig;

    /**
     * 通用下载请求
     *
     * @param fileName 文件名称
     * @param delete 是否删除
     */
    @GetMapping("common/download")
    public void fileDownload(String fileName, Boolean delete, HttpServletResponse response, HttpServletRequest request)
    {
        try
        {
            if (!FileUtils.checkAllowDownload(fileName))
            {
                throw new Exception(StringUtils.format("文件名称({})非法,不允许下载。 ", fileName));
            }
            String realFileName = System.currentTimeMillis() + fileName.substring(fileName.indexOf("_") + 1);
            String filePath = RuoYiConfig.getDownloadPath() + fileName;

            response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
            FileUtils.setAttachmentResponseHeader(response, realFileName);
            FileUtils.writeBytes(filePath, response.getOutputStream());
            if (delete)
            {
                FileUtils.deleteFile(filePath);
            }
        }
        catch (Exception e)
        {
            log.error("下载文件失败", e);
        }
    }

    /**
     * 通用上传请求
     */
    @PostMapping("/common/upload")
    public AjaxResult uploadFile(MultipartFile file) throws Exception
    {
        try
        {
            // 上传文件路径
            String filePath = RuoYiConfig.getUploadPath();
            // 上传并返回新文件名称
            String fileName = FileUploadUtils.upload(filePath, file);
            String url = serverConfig.getUrl() + fileName;
            AjaxResult ajax = AjaxResult.success();
            ajax.put("fileName", fileName);
            ajax.put("url", url);
            return ajax;
        }
        catch (Exception e)
        {
            return AjaxResult.error(e.getMessage());
        }
    }

    /**
     * 通用上传请求返回磁盘路径
     */
    @PostMapping("/common/uploadWithAbsolutePath")
    public AjaxResult uploadFileWithAbsolutePath(MultipartFile file) throws Exception
    {
        try
        {
            // 上传文件路径
            String filePath = RuoYiConfig.getUploadPath();
            // 上传并返回新文件名称
            String fileName = FileUploadUtils.uploadWithAbsolutePath(filePath, file);
            AjaxResult ajax = AjaxResult.success();
            ajax.put("uploadpath", filePath+ File.separator+fileName);
            return ajax;
        }
        catch (Exception e)
        {
            return AjaxResult.error(e.getMessage());
        }
    }

    /**
     * 本地资源通用下载
     */
    @GetMapping("/common/download/resource")
    public void resourceDownload(String resource, HttpServletRequest request, HttpServletResponse response)
            throws Exception
    {
        try
        {
            if (!FileUtils.checkAllowDownload(resource))
            {
                throw new Exception(StringUtils.format("资源文件({})非法,不允许下载。 ", resource));
            }
            // 本地资源路径
            String localPath = RuoYiConfig.getProfile();
            // 数据库资源地址
            String downloadPath = localPath + StringUtils.substringAfter(resource, Constants.RESOURCE_PREFIX);
            // 下载名称
            String downloadName = StringUtils.substringAfterLast(downloadPath, "/");
            response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
            FileUtils.setAttachmentResponseHeader(response, downloadName);
            FileUtils.writeBytes(downloadPath, response.getOutputStream());
        }
        catch (Exception e)
        {
            log.error("下载文件失败", e);
        }
    }

    /**
     * 本地资源通用下载
     */
    @GetMapping("/common/download/resourceeasy")
    public void resourceDownloadEasy(String resource, HttpServletRequest request, HttpServletResponse response)
            throws Exception
    {
        try
        {
            if (!FileUtils.checkAllowDownload(resource))
            {
                throw new Exception(StringUtils.format("资源文件({})非法,不允许下载。 ", resource));
            }
            response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
            FileUtils.setAttachmentResponseHeader(response, resource);
            FileUtils.writeBytes(resource, response.getOutputStream());
        }
        catch (Exception e)
        {
            log.error("下载文件失败", e);
        }
    }
}