主要介绍两种方式实现文件预览方式,一种是通过前端插件匹配不同文件,另一种就是使用已经完善的文件预览系统。我更推荐使用第二种方式,因为这样会少去很多工作量本文主要介绍第一种方式,第二种方式会出现在另外一篇文章中。

本文基于若依前后分离版本实现文件预览功能若依官网链接

通过前端插件匹配文件预览:有两个思路一个是传blob流,然后将流转成对应文件格式,再进行预览。另一个通过后端将文件地址映射出来,然后通过浏览器进行访问。两种方式各有优缺点blob流方式在进行本地测试阶段没有发现任何问题,但是当部署服务器,就会出现文件传输速度问题,如果是内网使用速度可以接收,但是外网使用,预览速度根本无法接收blob流方式预览就相当于下载完文件后,再进行预览,所以速度很慢浏览器打开方式只支持浏览器支持预览的文件,很多文件格式支持。总之,这两种文件预览方式的缺陷还是很大的,如果文件预览支持格式较少,文件都不是很大,适用于个人学习,只使用电脑端使用而不使用手机端时,可以进行使用。

1.文件操作时间简单调用数据库的时间长很多。为了避免前端访问后端接口因为超市报错,将超时时间设置长一点。将ruoyiui/src/utils/request.js文件下的timeout设置为6000000,可以根据自己的使用情况进行设置

// 创建axios实例
const service = axios.create({
  // axios请求配置baseURL选项表示请求URL公共部分
  baseURL: process.env.VUE_APP_BASE_API,
  // 超时
  timeout: 6000000
})

2.文件预览之前,先要进行文件上传。文件上传内容可以看我写的《SpringBoot实现文件上传和下载》。后端在ruoyiadmin/src/main/resources/application.yml文件最后添加文件路径配置,文件地址可以自行设置。

prop:
	filePath: d:/csdn/onlineFile/

3.后端返回文件流的接口,其中filePath是在controller类中通过@Value导入

    @Value("${prop.filePath}")
    private String filePath;
/**
     * 根据文件名下载文件
     *
     * @param fileName 文件名,是由文件id+文件扩展名(extName)组成
     * @return 文件信息
     * @throws IOException
     */
@GetMapping("/download")
public ResponseEntity<InputStreamResource> download(String fileName) throws IOException {
    String path = filePath + fileName;
    FileSystemResource file = new FileSystemResource(path);

    // 设置响应头
    HttpHeaders headers = new HttpHeaders();
    headers.add("Content-Disposition", String.format("attachment; filename="%s"", file.getFilename()));

    return ResponseEntity
    .ok()
    .headers(headers)
    .contentLength(file.contentLength())
    .contentType(MediaType.parseMediaType("application/octet-stream"))
    .body(new InputStreamResource(file.getInputStream()));
}
import request from "@/utils/request";
let fileUrl = '后端controller的RequestMapping的值'
export function getPrevieweFile(fileName) {
  return request({
    url: fileUrl + '/download',
    method: 'get',
    params: {
      fileName
    },
    responseType: 'blob'
  })
}
getPrevieweFile(fileName).then(res => {
  let blob = new Blob([res]);


  //通过switch调用不同类型文件的处理函数
  switch (file.extName) {
    case '.txt':
      this.previewData.type = 'txt';
      this.handleTxtFilePreview(blob);
      break;
    case '.png':
      this.previewData.type = 'image';
      this.handleImageFilePreview(blob);
      break;
    case '.jpg':
      this.previewData.type = 'image';
      this.handleImageFilePreview(blob);
      break;
    case '.xls':
      this.previewData.type = 'excel';
      this.handleExcelFilePreview(blob);
      break;
    case '.xlsx':
      this.previewData.type = 'excel';
      this.handleExcelFilePreview(blob);
      break;
    case '.docx':
      this.previewData.type = 'word';
      this.handleWrodFilePreview(blob);
      break;
    case '.pdf':
      this.previewData.type = 'pdf';
      this.handlePdfFilePreview(blob);
      break;
  }
})
handleTxtFilePreview(blob) {
  let reader = new FileReader();
  reader.readAsArrayBuffer(blob);
  reader.onload = (evt) => {
    let ints = new Uint8Array(evt.target.result); //要使用读取内容,所以将读取内容转化成Uint8Array
    ints = ints.slice(0, blob.size); //截取一段读取内容
    let text = new TextDecoder('utf-8').decode(ints); //二进制缓存内容转化成中文(即也就是读取到的内容console.log(text);
  };
}
handleImageFilePreview(blob) {
  let url = URL.createObjectURL(blob);
}
handleExcelFilePreview(blob) {
  let reader = new FileReader();
  reader.readAsArrayBuffer(blob);
  reader.onload = (evt) => {
    let ints = new Uint8Array(evt.target.result); //要使用读取的内容,所以将读取内容转化成Uint8Array
    ints = ints.slice(0, blob.size);
    let workBook = xlsx.read(ints, { type: "array" });
    let sheetNames = workBook.SheetNames;
    let sheetName = sheetNames[0];
    let workSheet = workBook.Sheets[sheetName];


    //获取Excle内容,并将空内容用空值保存
    let excelTable = xlsx.utils.sheet_to_json(workSheet, { defval: '' });


    // 获取Excel头部
    let tableThead = Array.from(Object.keys(excelTable[0])).map(
      (item) => {
        return item
      }
    );
    this.previewData.content = {};
    this.previewData.content.tableContent = excelTable;
    this.previewData.content.tableThead = tableThead;
    this.previewDialogOpen = true;
  }


}
handleWrodFilePreview(blob) {
  this.previewDialogOpen = true;
  let docx = require("docx-preview");


  this.$nextTick(() => {
    docx.renderAsync(blob, this.$refs.word);
  })


}
<div ref="word">

</div>
handlePdfFilePreview(blob) {
  this.previewData.src = URL.createObjectURL(blob);
  let loadingTask = pdf.createLoadingTask(this.previewData.src);


  loadingTask.promise.then((pdf) => {
    this.previewData.pdfPages = pdf.numPages;
  })
}
<pdf v-for="pdfPage in previewData.pdfPages" :key="pdfPage" :page="pdfPage" :src="previewData.src"
  width="100%">
</pdf>
components: {
  pdf
}
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class MyWebMvcConfig implements WebMvcConfigurer {

    @Value("${prop.filePath}")
    private String filePath;

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        // 匹配到resourceHandler,将URL映射location,也就是本地文件夹
        registry.addResourceHandler("/data/webFiles/**").addResourceLocations("file:" + filePath);

    }
}
.antMatchers("/data/webFiles/**").permitAll()

文章开始提到的另外一种方式就是通过kkfileview实现文件预览,这种方式能够快速搭建文件系统支持多种格式的预览功能,预览速度快,可以作为一个独立的系统使用,不影响主系统架构,不受浏览器、电脑端或手机端的影响

后面文章会有专门讲解kkfileview如何配置打包使用。

文章链接

支持外网访问的kkfileview文件预览系统的详细使用过程

我也是个新手,上面很多内容不够完善,甚至有些是错误的,请大家见谅。这是我在学习过程中做的笔记,感觉对大家可能有所帮助才发出来的,大家可以选择性查看。我也是在不断学习,不断完善自己。如果我在学习过程中,感觉对大家有用的部分,也会再次分享给大家的。谢谢!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注