在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

公司实现文件上传技术选型采用后端SpringBoot/Cloud,前端vue Bootstrap ,静态服务器作为文件存储,文件上传功能单独抽取封装文件上传组件,可供所有的文件的操作。

后端框架版本
SpringBoot2.5.6
Spring-Cloud2020.0.4
mysql8.0.26
pagehelper1.3.1
Mybatis2.2.0
Redis5.0
Fastjson1.2.78
前端框架版本
Vue2.6.11
axios0.24.0
vue-router3.5.3
Bootstrap4.6.2

一、前端部分
1. 讲师页面

讲师页面作为文件上传父页面

   <div class="form-group">
                <label class="col-sm-2 control-label">头像</label>
                <div class="col-sm-10">
                  <file v-bind:input-id="'image-upload'"
                            v-bind:text="'上传头像'"
                            v-bind:suffixs="['jpg', 'jpeg', 'png']"
                            v-bind:use="FILE_USE.TEACHER.key"
                            v-bind:after-upload="afterUpload"></file>
                  <div v-show="teacher.image" class="row">
                    <div class="col-md-4">
                      <img v-bind:src="teacher.image" class="img-responsive">
                    </div>
                  </div>

                </div>
              </div>
2. js部分
<script>
import File from "../../components/file";
export default {
  components: {Pagination, BigFile,File},
  name: "business-teacher",
  data: function () {
    return {
      teacher: {},
      teachers: [],
      FILE_USE: FILE_USE,
    }
  },
  
  methods: {
    /**
     * 点击【新增】
     */
    add() {
      let _this = this;
      _this.teacher = {};
      $("#form-modal").modal("show");
    },

    /**
     * 点击【编辑】
     */
    edit(teacher) {
      let _this = this;
      _this.teacher = $.extend({}, teacher);
      $("#form-modal").modal("show");
    },

    /**
     * 列表查询
     */
    list(page) {
      let _this = this;
      Loading.show();
      _this.$api.post(process.env.VUE_APP_SERVER + '/business/admin/teacher/list', {
        page: page,
        size: _this.$refs.pagination.size,
      }).then((response) => {
        Loading.hide();
        let resp = response.data;
        _this.teachers = resp.content.list;
        _this.$refs.pagination.render(page, resp.content.total);

      })
    },

    /**
     * 点击【保存】
     */
    save() {
      let _this = this;

      // 保存校验
      if (1 != 1
          || !Validator.require(_this.teacher.name, "姓名")
          || !Validator.length(_this.teacher.name, "姓名", 1, 50)
          || !Validator.length(_this.teacher.nickname, "昵称", 1, 50)
          || !Validator.length(_this.teacher.image, "头像", 1, 100)
          || !Validator.length(_this.teacher.position, "职位", 1, 50)
          || !Validator.length(_this.teacher.motto, "座右铭", 1, 50)
          || !Validator.length(_this.teacher.intro, "简介", 1, 500)
      ) {
        return;
      }

      Loading.show();
      _this.$api.post(process.env.VUE_APP_SERVER + '/business/admin/teacher/save', _this.teacher).then((response) => {
        Loading.hide();
        let resp = response.data;
        if (resp.success) {
          $("#form-modal").modal("hide");
          _this.list(1);
          Toast.success("保存成功!");
        } else {
          Toast.warning(resp.message)
        }
      })
    },
    afterUpload(resp) {
      let _this = this
      let image = resp.content.path;
      _this.teacher.image = image
    }
  }
}
</script>

3. 文件上传组件
<template>
  <div>
    <button type="button" v-on:click="selectFile()" class="btn btn-white btn-default btn-round">
      <i class="ace-icon fa fa-upload"></i>
      {{text}}
    </button>
    <input class="hidden" type="file" ref="file" v-on:change="uploadFile()" v-bind:id="inputId+'-input'">
  </div>a
</template>

<script>
export default {
  name: 'file',
  props: {
    text: {
      default: "上传文件"
    },
    inputId: {
      default: "file-upload"
    },
    suffixs: {
      default: []
    },
    use: {
      default: ""
    },
    afterUpload: {
      type: Function,
      default: null
    },
  },
  data: function () {
    return {
    }
  },
  methods: {
    uploadFile () {
      let _this = this;
      let formData = new window.FormData();
      let file = _this.$refs.file.files[0];

      // 判断文件格式
      let suffixs = _this.suffixs;
      let fileName = file.name;
      let suffix = fileName.substring(fileName.lastIndexOf(".") + 1, fileName.length).toLowerCase();
      let validateSuffix = false;
      for (let i = 0; i < suffixs.length; i++) {
        if (suffixs[i].toLowerCase() === suffix) {
          validateSuffix = true;
          break;
        }
      }
      if (!validateSuffix) {
        Toast.warning("文件格式不正确!只支持上传:" + suffixs.join(","));
        $("#" + _this.inputId + "-input").val("");
        return;
      }

      // key:"file"必须和后端controller参数名一致
      formData.append('file', file);
      formData.append('use', _this.use);
      Loading.show()
      _this.$api.post(process.env.VUE_APP_SERVER + '/file/admin/upload', formData).then((response) => {
        Loading.hide()

        let resp = response.data
        console.log("上传文件成功:", resp)

        //回调父组件函数
        _this.afterUpload(resp)

        //解决 同一个文件上传2次或者大于3次,不会发生变化
        $("#" + _this.inputId + "-input").val("");
      })
    },

    selectFile() {
      let _this = this
      // console.log("_this.inputId",_this.inputId)
      $("#" + _this.inputId + "-input").trigger("click");
    }
  },
}
</script>

<style scoped>
</style>

二、后端
2.1. 配置
package com.course.file.config;

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 SpingMvConfig implements WebMvcConfigurer {

    @Value("${file.path}")
    private String FILE_PATH;

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/f/**").addResourceLocations("file:" + FILE_PATH);
    }
}

2.2. 配置
# 应用名称
spring.application.name=file
# 应用端口
server.port=9003
# 注册到eureka
eureka.client.service-url.defaultZone=http://localhost:8761/eureka

# 请求访问前缀
server.servlet.context-path=/file

# 本地存储静态文件路径
file.path=D:/file/imooc/course/
# 访问静态文件路径(用于文件回显或者文件下载)
file.domain=http://127.0.0.1:9000/file/f/

# 文件大小(如果搭建大小超过此配置的大小或抛出异常)
spring.servlet.multipart.max-file-size=50MB
# 请求大小
spring.servlet.multipart.max-request-size=50MB


2.3. api接口
package com.course.file.controller.admin;

import java.util.Date;

import com.course.server.dto.FileDto;
import com.course.server.dto.ResponseDto;
import com.course.server.enums.FileUseEnum;
import com.course.server.service.FileService;
import com.course.server.util.UuidUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.File;
import java.io.IOException;

@RequestMapping("/admin")
@RestController
public class UploadController {
    public static final Logger LOG = LoggerFactory.getLogger(UploadController.class);
    public static final String BUSINESS_NAME = "文件上传";

    @Value("${file.domain}")
    private String FILE_DOMAIN;
    @Value("${file.path}")
    private String FILE_PATH;
    @Resource
    private FileService fileService;

    @PostMapping("/upload")
    public ResponseDto upload(@RequestParam MultipartFile file, String use) throws IOException {
        String fileSize = String.valueOf(file.getSize());
        LOG.info("上传文件开始: {}", file);
        LOG.info("获取上传文件名称: {}", file.getOriginalFilename());
        LOG.info("上传文件大小: {}", fileSize);

        // 保存文件到本地
        FileUseEnum useEnum = FileUseEnum.getByCode(use);
        String key = UuidUtil.getShortUuid();
        String fileName = file.getOriginalFilename();
        String suffix = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();

        //如果文件夹不存在,则创建
        String dir = useEnum.name().toLowerCase();
        File fullDir = new File(FILE_PATH + dir);
        if (!fullDir.exists()) {
            fullDir.mkdirs();
        }
        String path = dir + File.separator + key + "." + suffix;
        String fullPath = FILE_PATH + path;
        File dest = new File(fullPath);
        file.transferTo(dest);
        LOG.info("上传文件全路径: {}", dest.getAbsolutePath());

        LOG.info("保存文件记录开始: {}");
        FileDto fileDto = new FileDto();
        fileDto.setPath(path);
        fileDto.setName(fileName);
        fileDto.setSuffix(suffix);
        fileDto.setUse(use);
        fileDto.setSize(Math.toIntExact(file.getSize()));
        fileService.save(fileDto);


        ResponseDto responseDto = new ResponseDto();
        fileDto.setPath(FILE_DOMAIN + path);
        responseDto.setContent(fileDto);
        return responseDto;

    }
}

Logo

前往低代码交流专区

更多推荐