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

element-ui文件上传下载组件:
具备上传、下载和删除功能。
不自动上传,附件选择后只将文件加入待上传列表,点击确认上传按钮后上传到后台服务器,已上传的文件通过表格的形式展示在上方表格中。
删除和上传权限可配置。
效果如下:
权限:上传、删除、下载,已上传列表无数据
权限:上传、删除、下载,已下载列表中包含数据
权限:仅下载

代码如下:

/*
 * @Description: element-ui文件上传下载组件(不自动上传)
 * @Author: yiwenli
 * @Date: 2023-03-30
 */
Vue.component('fileUpload', {
    name: 'fileUpload',
    template: /* html */ `<div>
        <div>已上传文件列表</div>
        <el-table :data="uploadedFileList" :show-header="false">
                <el-table-column prop="fileName" width="300" align="center"></el-table-column>
                <el-table-column prop="operate" width="200" align="center">
                    <template slot-scope="scope">
                        <el-button class="el-icon-download" type="text" @click="fileDownload(scope.row)">下载</el-button>
                        <el-button class="el-icon-delete" type="text" @click="fileDeleteInServer(scope.row)" v-if="deleteAble">删除</el-button>
                    </template>
                </el-table-column>
        </el-table>
		<el-form-item v-if="uploadAble">
			<el-upload
                action="#"
                :auto-upload="false"
				:multiple="true"
                :file-list="toUploadFileList"
                :on-change="fileChange"
                :on-remove="fileRemove"
                >
                    <el-button slot="trigger" size="small" type="primary">附件选择</el-button>
                    <el-button size="small" plain @click="fileUpload">确认上传</el-button>
			</el-upload>
		</el-form-item>
	</div>`,
    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);
        }
    }
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值