【文件系统】Vue+SpringBoot模拟文件系统(1)

本文档详细介绍了如何使用Vue和SpringBoot构建一个简单的文件管理系统,包括展示文件列表、新建文件夹和上传文件的功能。前端利用VueCli2和ElementUI展示文件列表,后端使用SpringBoot处理文件操作请求,通过MultipartFile处理文件上传,并配置了multipart上传大小限制。
摘要由CSDN通过智能技术生成

【文件系统】Vue+SpringBoot模拟文件系统

0. 相关知识预告

  • Vue Cli2
  • ElementUI
  • SpringBoot
  • MultipartFile 【form-data】

1. 展示文件列表模拟

1.1 前端

使用Vue Cli2 + ElementUI

1.1.1 展示样式介绍

  • 使用el-table展示列表,关键属性是 :data 绑定里面所有行数据【tableData是自定义的一个变量】
  • el-table只需要我们设计表头,数据会根据我们定义的一个数组变量内容自动加载,但只有加载el-table有的字段
  • 使用<template>相关标签是为了自定义表头,相关样式可以去elementUI官网学习。

效果如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-m3gdhf44-1653312947040)(C:\Users\86137\AppData\Roaming\Typora\typora-user-images\image-20220523202154124.png)]

代码如下:【值得注意的就是min-width=100%,很好用】

<el-table v-loading="loading" :data="tableData" style="width: 100%" :default-sort="{prop: 'date', order: 'descending'}" max-height="1080" element-loading-text="拼命加载中" element-loading-spinner="el-icon-loading" v-contextmenu:contextmenu>
        <!-- min-width100%能实现header拉长,name独大 -->
        <el-table-column prop="name" label="文件名" min-width="100%">
            <template slot="header">
                <i class="el-icon-document hidden-xs-only"></i>
                <span>文件名</span>
                <el-upload class="upload" action="/file/uploadFile" :data="data" multiple :show-file-list="false" :before-upload="beforeUpload">
                    <el-button size="small" type="primary">点击上传</el-button>
                </el-upload>
            </template>
        </el-table-column>

        <el-table-column prop="lastModifyTime" label="修改时间" sortable width="180">
            <template slot="header">
                <span>修改时间</span>
            </template>
        </el-table-column>
        <el-table-column prop="size" label="大小" sortable width="180">
            <template slot="header">
                <span>大小</span>
            </template>
        </el-table-column>
        <el-table-column prop="operation" label="操作" width="180">
            <template slot-scope="scope">
                <el-button type="text" icon="el-icon-download"></el-button>
                <el-button type="text" icon="el-icon-close" @click="confirm"></el-button>
            </template>
        </el-table-column>
</el-table>

1.1.2 异步访问接口

  • 参数方面直接传入,这样是属于params式传入。参数以json串形式传过去则为query请求体式传输,一定要注意这里。
  • 因为post还可以通过params式传入,和get一样拼接在地址后面。
  • 后端对于两种传参的处理是不一样的。axios默认post为query传输,get为params传输
this.$http.post("/file/showAllFiles", {
    curUrl: "\\d\\c", 
    uid: 9
}).then((res) => {
    this.tableData = res.data;
});

1.2 后端SpringBoot

1.2.1 Controller

  • post映射指定
  • @ResponseBody表示该控制器自动将结果转为json串异步返回
  • 参数!!!重中之重。通过map并指定body来接收前端的json串,要么你就弄一个实体对象接收比如Student对象。千万不能用【@RequestParam(“curUrl”) String curUrl】这样接收,这样只允许post请求中的params式参数【就是get类型】,所以如果用了RequestParam,即使前端请求成功,后端也拿不到任何数据。因为这样spring就不认json串。我们需要RequestBody接受query参数
  • 注意,需要前端传参uid,访问用户自身专属的文件夹
  • 提前把前端传的curUrl相对路径转换为本地绝对路径
@PostMapping("/showAllFiles")
@ResponseBody
/**
* @param uid 表示用户id
* @param curUrl 表示当前所在的文件夹位置,返回该文件夹下的所有文件
*               注意该接口只对文件夹有效
*/
public List showAllFiles(@RequestBody Map<String, String> map) {
    String localUrl = store + map.get("uid") + map.get("curUrl");
    System.out.println(localUrl);
    List<FileInfo> res = fileService.showAllFiles(localUrl);
    return res;
}

1.2.2 Service

  • 大体通过java导入的File包进行处理
  • File包能够直接访问本地文件夹,直接获取文件列表
  • 我还需要文件的大小,文件的最后修改时间,这些都可以直接获取
  • 注意 file.length() 就是文件的大小了
/**
* @param curUrl 传入的是本地绝对路径
*
* @return 返回当前目录下的所有FileInfo(不包括子代)
*          info内容包括文件/目录名,后缀,文件大小,文件最后修改时间(已经格式化),是否是目录
*/
@Override
public List<FileInfo> showAllFiles(String curUrl) {
    File dir = new File(curUrl);
    //先判断文件夹是否存在
    if(!dir.exists()) {
        System.out.println("目录不存在");
        return null;
    }

    //获取文件列表
    File[] fileList = dir.listFiles();
    //FileInfo是我自定义的一个实体类,把文件中我需要的信息注入作为一个单位返回
    List<FileInfo> res = new ArrayList<>();
    DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    for(File file : fileList) {
    	//如果是目录,不加入大小,默认“-”
        if(file.isDirectory()) {
            res.add(new FileInfo(file.getName()," ", "-", df.format(new Date(file.lastModified())), 1));
        }else {
            String name = file.getName();
            //得到的结果是B,字节
                double len = Double.valueOf(file.length());
                String size = "";
                if(len < 1024) {
                    size = "" + String.format("%.2f", len) + "b";
                }else if(len >= 1024 && len < 1048576) {
                    size = "" + String.format("%.2f", len/1024) + "kb";
                }else if(len >= 1048576 && len < 1073741824) {
                    size = "" + String.format("%.2f", len/1048576) + "mb";
                }
                res.add(new FileInfo(name, name.substring(name.lastIndexOf(".")+1), size, df.format(new Date(file.lastModified())), 0));
            }
        }
    }

    return res;
}

1.3 效果展示

  • 访问用户9的\d\c\a位置
    在这里插入图片描述

  • 刷新页面,渲染vue组件时自动请求showAllFiles接口
    在这里插入图片描述

  • 成功访问

2. 新建文件夹模拟

2.1 前端

前端直接提供一个按钮去访问对应接口就行,这里不演示。

2.2 后端

2.2.1 Controller

  • 同理接收body参数,所以用map和RequestBody
  • 需要知道是哪位用户(uid)在哪里新建(curUrl),找到对应的本地路径
@PostMapping("/newFolder")
@ResponseBody
/**
* @param curUrl 表示当前创建的文件夹所在的位置
*/
public Integer newFloder(@RequestBody Map<String, String> map) {
    String localUrl = store + map.get("uid") + map.get("curUrl");
    int res = fileService.newFolder(localUrl);
    return res;
}

2.2.2 Service

  • 调用Files的静态方法创建文件夹
  • 成功返回1,失败返回0
@Override
public Integer newFolder(String localUrl) {
    //创建本地文件夹,curUrl应该包含name
    try{
        Files.createDirectories(Paths.get(localUrl));
        return 1;
    }catch (IOException e){
        e.printStackTrace();
        return 0;
    }
}

值得注意的是:我们需要在注册的时候,先为当前注册成功的用户创建一个专属文件夹。

2.3 效果展示

  • 模拟接口
    在这里插入图片描述

  • 查看结果【创建成功】
    在这里插入图片描述

3. 上传文件模拟

这里要提醒,需要学习form-data和multipart

3.0 form-data和multipart

enctype:一个html表单的post请求过程中enctype【中文是编码方式】有三种类型

Content-Type:用于定义用户的浏览器或相关设备如何显示将要加载的数据,或者如何处理将要加载的数据

  • application/x-www-urlencoded

    • 编码方式是ASCII
    • 是最普通的post编码,数据会被编码到body中传输
    • 表单默认是这个
  • multipart/form-data【其实了解他是个传文件的就差不多了】

    • 是基于post方法来传递二进制数据的,一般能用来传递文件

    • 如图,解释一下,每一行的一个------WebKitFormBoundarynRpsHcUvTeBqpdsH是一个boundary,是可以自定义的,是一个分隔符,你就当他用来分隔各个参数的就行了,有头有尾。

    • 参数名与参数值之间会有两行换行,这是官方规定的格式,照着了解就行。

    • 整体格式总结

      --分隔符(boundary)[换行]
      Content-Disposition: form-data; name="参数名"[换行] 
      [换行]
      参数值[换行]
      --分隔符(boundary)[换行]
      Content-Disposition: form-data; name="图片名"; filename="图片文件名"[换行]
      Content-Type: 类型[换行]
      [换行]
      图片文件的二进制内容[换行]
      --分隔符(boundary)--
      

在这里插入图片描述

  • text-plain
    • 传递的数据是文本数据,既然是文本,浏览器不会做过多处理。

3.1 前端

使用Vue Cli2 + ElementUI

  • 使用el-upload进行用户本地文件选取以及自动上传
  • 注意使用multiple,不然一个用户只能传一个文件
  • 注意也不要添加limit参数
  • 默认就是自动上传
  • 这里比较关键是data是能传入额外参数,而我们后端需要知道uid和当前路径
  • 注意这里使用的是el组件的action,data是属于query参数,直接拼在url后的,后端能直接用@RequestParam
<el-upload class="upload" 
           action="/file/uploadFile" 
           data="{curUrl:'\\d\\c\\a', uid:9}"
           multiple 
           :show-file-list="false">
    <el-button size="small" type="primary">点击上传</el-button>
</el-upload>


  • 效果如下:
    在这里插入图片描述在这里插入图片描述
  • 选择文件上传即可。

3.2 后端

3.2.1 Controller

  • 不多说了
  • 前端data是属于query参数,直接拼在url后的,后端能直接用@RequestParam
@PostMapping("/uploadFile")
@ResponseBody
public Integer uploadFile(@RequestParam("curUrl") String curUrl, @RequestParam("uid") Integer uid,@RequestParam("file") MultipartFile file) {
    String localUrl = store + uid + curUrl;
    fileService.uploadFile(file, localUrl);
    return 1;
}

3.2.2 Service

  • 这里我封装了一个工具类,待会介绍
@Override
public Integer uploadFile(MultipartFile file, String curUrl) {
    MultipartFileUtil.addFile(file, curUrl);
    return 1;
}

3.2.3 springboot的yaml配置

  • 对spirngboot的application.yaml或者其他配置文件都好,配置multipart相关参数
  • 不设置大小,默认1m作为单个文件上传上限
spring:
  # web处理multipart请求懒加载
  servlet:
    multipart:
      resolve-lazily: true
      #设置单个文件大小,单位MB和KB都可以
      max-file-size: 1000MB
      #设置总上传的数据大小,单位MB和KB都可以
      max-request-size: 10000MB
    tomcat:
      max-swallow-size: 100MB

3.2.4 重点!MultipartFileUtil工具类

  • 比较重要的就是获取multipartFile的文件名file.getOriginalFilename();

  • 剩下考察你对文件IO流熟不熟悉,这里采用一个手动缓存读写。

  • 毕竟都是二进制而已,直接读写即可。

  • 源码,可以直接复制使用

import org.springframework.web.multipart.MultipartFile;
import java.io.*;

public class MultipartFileUtil {
    public static void addFile(MultipartFile file,String uri){
        OutputStream outputStream = null;
        InputStream inputStream = null;
        String fileName = null;
        try {
            inputStream = file.getInputStream();
            fileName = file.getOriginalFilename();
            //log.info("fileName="+fileName);
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            // 2、保存到临时文件
            // 1K的数据缓冲
            byte[] bs = new byte[1024];
            // 读取到的数据长度
            int len;
            // 输出的文件流保存到本地文件
            File tempFile = new File(uri);
            if (!tempFile.exists()) {
                tempFile.mkdirs();
            }

            //跨平台写法,windows和linux都适用
            outputStream = new FileOutputStream(tempFile.getPath() + File.separator + file.getOriginalFilename());

            // 开始读取和写入os
            while ((len = inputStream.read(bs)) != -1) {
                outputStream.write(bs, 0, len);
            }

        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 完毕,关闭所有链接
            try {
                outputStream.close();
                inputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

3.3 效果展示

  • 前端选择文件,确定后自动上传
    在这里插入图片描述

  • 本地查看文件是否下载成功【成功下载到本地】
    在这里插入图片描述

  • 刷新页面
    在这里插入图片描述

4. 问题解决总结

  • el-table的一个min-width=100%使用解决表头问题

  • @RequestParam 或者 直接参数对应需要前端发送的请求参数是query参数【1对1】

  • 如果前端请求参数是body参数【json串】,后端要使用@RequestBody,配合map或者实体类进行接收

  • file.length是文件大小

  • 前后端对接的时候上传文件使用multipart/form-data,就是通过二进制流传递文件,el-upload能通过:data去传递额外参数

  • 多使用工具类封装

  • 通过配置文件处理multipart文件上传大小限制

  • 搞文件系统当然要想到用File包

  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 13
    评论
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

玖等了

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值