element-ui文件上传下载组件+后台对应接口

element-ui文件上传下载组件:
具备上传、下载和删除功能。
不自动上传,附件选择后只将文件加入待上传列表,点击确认上传按钮后上传到后台服务器,已上传的文件通过表格的形式展示在上方表格中。
删除和上传权限可配置。
效果如下:
element-ui文件上传下载组件+后台对应接口_第1张图片
element-ui文件上传下载组件+后台对应接口_第2张图片
element-ui文件上传下载组件+后台对应接口_第3张图片

代码如下:

/*
 * @Description: element-ui文件上传下载组件(不自动上传)
 * @Author: yiwenli
 * @Date: 2023-03-30
 */
Vue.component('fileUpload', {
    name: 'fileUpload',
    template: /* html */ `
已上传文件列表
附件选择 确认上传
`
, props: { // 原始文件数据 fileList: { type: Array, required: true, default: () => [], }, // 上传功能是否可用 uploadAble: { type: Boolean, required: false, default: true, }, // 删除功能是否可用 deleteAble: { type: Boolean, required: false, default: true, }, }, data() { return { // 已上传文件列表 uploadedFileList: [], // 待上传文件列表 toUploadFileList: [], }; }, computed: { // 上传路径 uploadUrl() { return requestUrlBase('/file/fileUpload'); }, // 删除路径 deleteUrl() { return requestUrlBase('/file/deleteFile'); }, // 下载路径 downloadUrl() { return requestUrlBase('/file/downLoadFile'); }, }, watch: { uploadedFileList() { this.$emit('update:fileList', this.uploadedFileList); }, fileList() { this.uploadedFileList = this.fileList; }, }, created() { this.uploadedFileList = this.fileList; }, methods: { /** * 文件上传 */ fileUpload() { if (this.toUploadFileList.length === 0) { this.$message.error('请先选择至少1个文件再上传'); return; } let formData = new FormData(); this.toUploadFileList.forEach((item) => { formData.append('file', item.raw); }); $http({ url: this.uploadUrl, method: 'post', data: formData, headers: { 'Content-Type': 'multipart/form-data' }, }) .then(({ data }) => { // 1、更新已上传文件列表 this.uploadedFileList = this.uploadedFileList.concat(data); // 2、更新待上传文件列表 let returnFileMap = new Map(data.map((value) => [value.fileName, value.fileId])); this.toUploadFileList = this.toUploadFileList .filter((item) => !returnFileMap.has(item.name)) .map((item) => { item.status = 'error'; return item; }); this.$message.success('附件上传完成'); }) .catch((e) => { this.$message.error(e.message || '附件上传失败'); }); }, /** * 文件修改 * @param {*} file 当前操作文件对象 * @param {*} fileList 文件列表 */ fileChange(file, fileList) { this.toUploadFileList = fileList; }, /** * 文件删除 * @param {Object} file 当前操作文件对象 * @param {Array} fileList 文件列表 */ fileRemove(file, fileList) { this.toUploadFileList = fileList; }, /** * 文件从服务器端删除 * @param {Object} file 文件对象 */ fileDeleteInServer(file) { this.$confirm('确定删除?', '提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning', }) .then(() => { $http({ url: this.deleteUrl, method: 'get', params: requestParam(file, 'get'), headers: { 'Content-Type': 'application/x-www-form-urlencoded', }, }) .then(() => { this.$message.success('文件删除成功'); this.uploadedFileList.splice( this.uploadedFileList.findIndex((item) => item.fileId === file.fileId), 1 ); }) .catch((e) => { this.$message.error(e.message || '文件删除失败'); }); }) .catch(() => { this.$message({ type: 'info', message: '已取消删除', }); }); }, /** * 文件下载 * @param {Object} file 文件对象 */ fileDownload(file) { let params = { fileId: file.fileId, fileName: file.fileName, userOrgId: Session.get('userInfo').orgId, }; this.postDownloadFile(params, this.downloadUrl); }, /** * 以post方式传参并下载文件 * @param {Object} params 请求需要的参数 * @param {String} url 请求url地址 */ postDownloadFile(params, url) { // params是post请求需要的参数,url是请求url地址 const form = document.createElement('form'); form.style.display = 'none'; form.action = url; form.method = 'post'; document.body.appendChild(form); // 动态创建input并给value赋值 for (const key in params) { const input = document.createElement('input'); input.type = 'hidden'; input.name = key; input.value = params[key]; form.appendChild(input); } form.submit(); form.remove(); }, }, });
<file-upload
     :file-list.sync="fileList"
     :upload-able="true"
     :delete-able="true"
>file-upload>

后端:

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.io.file.FileNameUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.crypto.digest.DigestUtil;
import com.ieslab.model.Result;
import com.ieslab.pfjawebsvr.modules.file.domain.FileVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.Resource;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.util.*;

/**
 * @author
 * @ClassName FileOpController
 * @Description 附件上传下载
 * @date 2022年03月16日 14:20
 */
@Api(tags = "附件上传下载")
@RestController
@RequestMapping("/file")
@Slf4j
public class FileController {

    @ApiOperation("附件上传")
    @PostMapping("/fileUpload")
    public Result upLoadFile(@RequestHeader("userOrgId") String userOrgId, @RequestParam("file") MultipartFile[] files) {
        if (files.length == 0) {
            return Result.error("文件为空");
        }
        if (ObjectUtil.isNull(userOrgId)) {
            userOrgId = "null";
        }
        List<FileVO> fileVOList = new ArrayList<>();
        try {
            String basePath = System.getenv("PFJA_HOME") + "/file/" + userOrgId + "/";
            for (MultipartFile multipartFile : files) {
                String fileName = multipartFile.getOriginalFilename();
                //生成文件唯一has256值
                String hashValue = DigestUtil.sha256Hex(multipartFile.getBytes());
                String filePath = basePath + FileNameUtil.getPrefix(fileName) + "&" + hashValue + "." + FileNameUtil.getSuffix(fileName);
                File file = FileUtil.file(filePath);
                //实现文件存储
                FileUtil.writeBytes(multipartFile.getBytes(), file);
                fileVOList.add(new FileVO(hashValue, fileName));
            }
            return Result.ok(fileVOList);
        } catch (Exception e) {
            return Result.error(e.getMessage());
        }
    }

    @ApiOperation("附件下载")
    @PostMapping(value = "/downLoadFile")
    public void downLoadFile(@RequestParam("userOrgId") String userOrgId, @RequestParam("fileId") String fileId, @RequestParam("fileName") String fileName, HttpServletResponse response) {
        if (ObjectUtil.isNull(userOrgId)) {
            userOrgId = "null";
        }
        String basePath = System.getenv("PFJA_HOME") + "/file/" + userOrgId + "/";
        try {
            // 创建输出流对象
            ServletOutputStream outputStream = response.getOutputStream();
            //以字节数组的形式读取文件
            String filePath = basePath + FileNameUtil.getPrefix(fileName) + "&" + fileId + "." + FileNameUtil.getSuffix(fileName);
            byte[] bytes = FileUtil.readBytes(filePath);
            // 设置返回内容格式
            response.setContentType("application/octet-stream");
            // 把文件名按UTF-8取出并按ISO8859-1编码,保证弹出窗口中的文件名中文不乱码
            // 中文不要太多,最多支持17个中文,因为header有150个字节限制。
            // 这一步一定要在读取文件之后进行,否则文件名会乱码,找不到文件
            fileName = new String(fileName.getBytes("UTF-8"), "UTF-8");
            // 设置下载弹窗的文件名和格式(文件名要包括名字和文件格式)
            response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
            // 返回数据到输出流对象中
            outputStream.write(bytes);
            // 关闭流对象
            IoUtil.close(outputStream);
        } catch (Exception e) {
            Result.error(e.getMessage());
        }
    }

    @ApiOperation("附件删除")
    @GetMapping("/deleteFile")
    public Result deleteFile(@RequestHeader("userOrgId") String userOrgId, @RequestParam("fileId") String fileId, @RequestParam("fileName") String fileName) {
        String basePath = System.getenv("PFJA_HOME") + "/file/" + userOrgId + "/";
        String filePath = basePath + FileNameUtil.getPrefix(fileName) + "&" + fileId + "." + FileNameUtil.getSuffix(fileName);
        File file = FileUtil.file(filePath);
        if (file.exists()) {
            boolean delete = file.delete();
            return Result.ok(delete);
        } else {
            return Result.ok(true);
        }
    }
}

你可能感兴趣的:(vue.js,elementui)