上传下载功能


一、上传功能

1. 后端代码
  • pom.xml

    引入依赖

        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.4</version>
        </dependency>
  • com.xx.xx.controller.CommonController
@Api(tags = "通用方法")
@RestController
@RequestMapping("/common")
public class CommonController {

    @Autowired
    CommonService commonService;

    @ApiOperation(value = "上传单文件", notes = "参数:")
    @PostMapping("/upload_file")
    public ServerResponse uploadFile(@RequestParam("file") MultipartFile[] file) throws IOException, InvalidExtensionException, FileUploadBase.FileSizeLimitExceededException {
        FileVo fileVo = commonService.uploadFile(file);
        return ServerResponse.createBySuccess("上传文件成功!",fileVo);
    }

}

  • com.xx.xx.service.CommonService
public interface CommonService {
    FileVo uploadFile(MultipartFile[] file) throws IOException, InvalidExtensionException, FileUploadBase.FileSizeLimitExceededException;
}
  • com.xx.xx.service.impl.CommonServiceImpl
@Service
public class CommonServiceImpl implements CommonService {
    @Value("${upload.dir}")
    String fileDir;

    @Override
    public FileVo uploadFile(MultipartFile[] files) throws IOException, InvalidExtensionException, FileSizeLimitExceededException {
        UUID uuid = UUID.randomUUID();
        String folderPath = fileDir + uuid.toString();
        MultipartFile file = files[0];

        // 文件大小校验
        FileUploadUtil.assertAllowed(file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION);

        String filePath = folderPath + "/" + file.getOriginalFilename();
        String dbPath = uuid.toString() + "/" + file.getOriginalFilename();
        FileUploadUtil.uploadFile(folderPath, filePath, file);

        FileVo fileVo = new FileVo();
        fileVo.setFileName(file.getOriginalFilename());
        fileVo.setFilePath(dbPath);
        return fileVo;
    }
}
  • com.xx.xx.utils.FileUploadUtil

    文件上传工具类

public class FileUploadUtil {
    /**
     * 默认大小 50M
     */
    public static final long DEFAULT_MAX_SIZE = 50 * 1024 * 1024;

    /**
     * 上传文件工具类
     *
     * @param path     文件夹位置
     * @param filePath 文件的全路径名
     * @param file     文件
     * @throws IOException
     */
    public static void uploadFile(String path, String filePath, MultipartFile file) throws IOException {
        File fileDir = new File(path);
        if (!fileDir.exists()) {
            fileDir.mkdirs();
        }
        try {
            file.transferTo(new File(filePath).getAbsoluteFile());
        } catch (IOException e) {
            e.printStackTrace();
            throw e;
        }
    }

    /**
     * 判断MIME类型是否是允许的MIME类型
     *
     * @param extension
     * @param allowedExtension
     * @return
     */
    public static boolean isAllowedExtension(String extension, String[] allowedExtension) {
        for (String str : allowedExtension) {
            if (str.equalsIgnoreCase(extension)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 获取文件名的后缀
     *
     * @param file 表单文件
     * @return 后缀名
     */
    public static String getExtension(MultipartFile file) {
        String extension = FilenameUtils.getExtension(file.getOriginalFilename());
        if (extension == null || extension.equals("")) {
            extension = MimeTypeUtils.getExtension(Objects.requireNonNull(file.getContentType()));
        }
        return extension;
    }

    /**
     * 文件大小校验
     *
     * @param file 上传的文件
     * @return
     * @throws FileSizeLimitExceededException 如果超出最大大小
     * @throws InvalidExtensionException
     */
    public static void assertAllowed(MultipartFile file, String[] allowedExtension)
            throws InvalidExtensionException, FileSizeLimitExceededException {
        long size = file.getSize();
        if (size > DEFAULT_MAX_SIZE)
            throw new FileSizeLimitExceededException("upload.exceed.maxsize", size, DEFAULT_MAX_SIZE / 1024 / 1024);
        String fileName = file.getOriginalFilename();
        String extension = getExtension(file);
        if (allowedExtension != null && !isAllowedExtension(extension, allowedExtension)) {
            if (allowedExtension == MimeTypeUtils.IMAGE_EXTENSION) {
                throw new InvalidExtensionException.InvalidImageExtensionException(allowedExtension, extension,
                        fileName);
            } else if (allowedExtension == MimeTypeUtils.FLASH_EXTENSION) {
                throw new InvalidExtensionException.InvalidFlashExtensionException(allowedExtension, extension,
                        fileName);
            } else if (allowedExtension == MimeTypeUtils.MEDIA_EXTENSION) {
                throw new InvalidExtensionException.InvalidMediaExtensionException(allowedExtension, extension,
                        fileName);
            } else if (allowedExtension == MimeTypeUtils.VIDEO_EXTENSION) {
                throw new InvalidExtensionException.InvalidVideoExtensionException(allowedExtension, extension,
                        fileName);
            } else {
                throw new InvalidExtensionException(allowedExtension, extension, fileName);
            }
        }

    }
}
  • com.xx.xx.utils.MimeTypeUtils

    媒体类型工具类

public class MimeTypeUtils
{
    public static final String IMAGE_PNG = "image/png";

    public static final String IMAGE_JPG = "image/jpg";

    public static final String IMAGE_JPEG = "image/jpeg";

    public static final String IMAGE_BMP = "image/bmp";

    public static final String IMAGE_GIF = "image/gif";
    
    public static final String[] IMAGE_EXTENSION = { "bmp", "gif", "jpg", "jpeg", "png" };

    public static final String[] FLASH_EXTENSION = { "swf", "flv" };

    public static final String[] MEDIA_EXTENSION = { "swf", "flv", "mp3", "wav", "wma", "wmv", "mid", "avi", "mpg",
            "asf", "rm", "rmvb" };

    public static final String[] VIDEO_EXTENSION = { "mp4", "avi", "rmvb" };

    public static final String[] DEFAULT_ALLOWED_EXTENSION = {
            // 图片
            "bmp", "gif", "jpg", "jpeg", "png",
            // word excel powerpoint
            "doc", "docx", "xls", "xlsx", "ppt", "pptx", "html", "htm", "txt",
            // 压缩文件
            "rar", "zip", "gz", "bz2",
            // 视频格式
            "mp4", "avi", "rmvb",
            // pdf
            "pdf" };

    public static String getExtension(String prefix)
    {
        switch (prefix)
        {
            case IMAGE_PNG:
                return "png";
            case IMAGE_JPG:
                return "jpg";
            case IMAGE_JPEG:
                return "jpeg";
            case IMAGE_BMP:
                return "bmp";
            case IMAGE_GIF:
                return "gif";
            default:
                return "";
        }
    }
}
  • com.xx.xx.exception.InvalidExtensionException

    文件上传 误异常类

public class InvalidExtensionException extends FileUploadException
{
    private static final long serialVersionUID = 1L;

    private final String[] allowedExtension;
    private final String extension;
    private final String filename;

    public InvalidExtensionException(String[] allowedExtension, String extension, String filename)
    {
        super("filename : [" + filename + "], extension : [" + extension + "], allowed extension : [" + Arrays.toString(allowedExtension) + "]");
        this.allowedExtension = allowedExtension;
        this.extension = extension;
        this.filename = filename;
    }

    public String[] getAllowedExtension()
    {
        return allowedExtension;
    }

    public String getExtension()
    {
        return extension;
    }

    public String getFilename()
    {
        return filename;
    }

    public static class InvalidImageExtensionException extends InvalidExtensionException
    {
        private static final long serialVersionUID = 1L;

        public InvalidImageExtensionException(String[] allowedExtension, String extension, String filename)
        {
            super(allowedExtension, extension, filename);
        }
    }

    public static class InvalidFlashExtensionException extends InvalidExtensionException
    {
        private static final long serialVersionUID = 1L;

        public InvalidFlashExtensionException(String[] allowedExtension, String extension, String filename)
        {
            super(allowedExtension, extension, filename);
        }
    }

    public static class InvalidMediaExtensionException extends InvalidExtensionException
    {
        private static final long serialVersionUID = 1L;

        public InvalidMediaExtensionException(String[] allowedExtension, String extension, String filename)
        {
            super(allowedExtension, extension, filename);
        }
    }

    public static class InvalidVideoExtensionException extends InvalidExtensionException
    {
        private static final long serialVersionUID = 1L;

        public InvalidVideoExtensionException(String[] allowedExtension, String extension, String filename)
        {
            super(allowedExtension, extension, filename);
        }
    }
}

2. 前端代码
  • element的upload组件

    这里设置只能上传一个文件。

  <el-upload
             ref="upload"
             action="/api/common/upload_file"
             :on-remove="handleRemove"
             :on-progress="handleFileUploadProgress"
             :before-remove="beforeRemove"
             :before-upload="beforeUpload"
             :on-error = "handleError"
             :on-success="uploadFileSuccess"
             :limit="1"
             :disabled="isUploading"
             :on-exceed="handleExceed"
             :file-list="fileList">
      <i class="el-icon-upload"></i>
      <div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
</el-upload>

<script>
  export default {
    data() {
      return {
          isUploading: false,
          fileList: []
      };
    },
    methods: {
        // 文件上传中处理
        handleFileUploadProgress(event, file, fileList) {
            this.isUploading = true;
        },
        // 文件上传错误处理
        handleError(err, file, fileList) {
            this.isUploading = false;
            this.$refs.upload.clearFiles();
            this.$message.error('上传失败!上传文件大小限制50MB。')
        },
        // 文件上传相关回调
        handleRemove(file, fileList) {
            // 删除文件及其目录
            if (this.formHandle.filePath !== '' && this.formHandle.filePath !== null){
                request({
                    method: 'get',
                    url: 'common/delete_file',
                    params: {
                        fid: this.formHandle.fid,
                        fileName: this.formHandle.filePath,
                    }
                }).then(() => {
                    this.$refs.upload.clearFiles();
                    this.formHandle.filePath = null;
                })
            }
        },
        // 上传限制处理
        handleExceed(files, fileList) {
            this.$message.warning(`当前限制上传 1 个文件,如需上传多个文件,请打包压缩后上传!`);
        },
        // 上传之前处理
        beforeUpload(file, fileList) {
            return this.$confirm(`确定上传 ${file.name} 到服务器吗 ?`, '上传提示', {
                type: 'warning',
            });
        },
        // 移除之前处理 
        beforeRemove(file, fileList) {
            return this.$confirm(`确定移除 ${file.name} ?`, '删除提示', {
                type: 'error',
            });
        },
        // 上传成功后处理
        uploadFileSuccess(response, file, fileList) {
            this.isUploading = false;
            this.uploadFilePath = response.data.filePath;
            console.log('uploadFileSuccess!~', this.uploadFilePath)
        },
    }
</script>

二、 下载功能

1. 后端代码
  • com.xx.xx.controller.CommonController
@Api(tags = "通用方法")
@RestController
@RequestMapping("/common")
public class CommonController {

    @Autowired
    CommonService commonService;

    @Autowired
    ExamineInfoService examineInfoService;

    @Value("${upload.dir}")
    String downloadPath;

    /**
     * 通用下载请求
     *
     * @param fileName 文件名称
     * @param delete 是否删除
     */
    @ApiOperation(value = "通用下载请求", notes = "参数:")
    @GetMapping("/download")
    public void fileDownload(String fileName, Boolean delete, HttpServletResponse response, HttpServletRequest request) {
        try {
            if (!FileUtils.checkAllowDownload(fileName)) {
                throw new Exception("文件非法,不允许下载。");
            }
            String realFileName = fileName.substring(fileName.lastIndexOf('/') + 1);
            String filePath = downloadPath + fileName;
            response.setContentType("application/octet-stream");
            FileUtils.setAttachmentResponseHeader(response, realFileName);
            FileUtils.writeBytes(filePath, response.getOutputStream());
            // 下载完是否删除该文件
            if (delete) {
                FileUtils.deleteFile(filePath);
            }
        } catch (Exception ignored) {
        }
    }
}
  • com.xx.xx.utils.FileUtils
public class FileUtils {

    public static final String[] DEFAULT_ALLOWED_EXTENSION = {
            // 图片
            "bmp", "gif", "jpg", "jpeg", "png",
            // word excel powerpoint
            "doc", "docx", "xls", "xlsx", "ppt", "pptx", "html", "htm", "txt",
            // 压缩文件
            "rar", "zip", "gz", "bz2",
            // 视频格式
            "mp4", "avi", "rmvb",
            // pdf
            "pdf"};

    /**
     * 获取文件类型
     * <p>
     * 例如: ruoyi.txt, 返回: txt
     *
     * @param fileName 文件名
     * @return 后缀(不含".")
     */
    public static String getFileType(String fileName) {
        int separatorIndex = fileName.lastIndexOf(".");
        if (separatorIndex < 0) {
            return "";
        }
        return fileName.substring(separatorIndex + 1).toLowerCase();
    }

    /**
     * 检查文件是否可下载
     *
     * @param resource 需要下载的文件
     * @return true 正常 false 非法
     */
    public static boolean checkAllowDownload(String resource) {
        // 禁止目录上跳级别
        if (StringUtils.contains(resource, "..")) {
            return false;
        }

        // 检查允许下载的文件规则
        return ArrayUtils.contains(DEFAULT_ALLOWED_EXTENSION, getFileType(resource));

        // 不在允许下载的文件规则
    }

    /**
     * 下载文件名重新编码
     *
     * @param response     响应对象
     * @param realFileName 真实文件名
     * @return
     */
    public static void setAttachmentResponseHeader(HttpServletResponse response, String realFileName) throws UnsupportedEncodingException {
        String percentEncodedFileName = percentEncode(realFileName);

        StringBuilder contentDispositionValue = new StringBuilder();
        contentDispositionValue.append("attachment; filename=")
                .append(percentEncodedFileName)
                .append(";")
                .append("filename*=")
                .append("utf-8''")
                .append(percentEncodedFileName);

        response.setHeader("Content-disposition", contentDispositionValue.toString());
    }

    /**
     * 百分号编码工具方法
     *
     * @param s 需要百分号编码的字符串
     * @return 百分号编码后的字符串
     */
    public static String percentEncode(String s) throws UnsupportedEncodingException {
        String encode = URLEncoder.encode(s, StandardCharsets.UTF_8.toString());
        return encode.replaceAll("\\+", "%20");
    }

    /**
     * 输出指定文件的byte数组
     *
     * @param filePath 文件路径
     * @param os       输出流
     * @return
     */
    public static void writeBytes(String filePath, OutputStream os) throws IOException {
        FileInputStream fis = null;
        try {
            File file = new File(filePath);
            if (!file.exists()) {
                throw new FileNotFoundException(filePath);
            }
            fis = new FileInputStream(file);
            byte[] b = new byte[1024];
            int length;
            while ((length = fis.read(b)) > 0) {
                os.write(b, 0, length);
            }
        } catch (IOException e) {
            throw e;
        } finally {
            if (os != null) {
                try {
                    os.close();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }
            if (fis != null) {
                try {
                    fis.close();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }
        }
    }

    /**
     * 删除文件
     *
     * @param filePath 文件
     */
    public static void deleteFile(String filePath) {
//        boolean flag = false;
        File file = new File(filePath);
        // 路径为文件且不为空则进行删除
        if (file.isFile() && file.exists()) {
            file.delete();
            // 获取父目录,并删除父目录文件夹
            File parentFile = file.getParentFile();
            if (parentFile.isDirectory() && parentFile.exists()){
                parentFile.delete();
            }
//            flag = true;
        }
    }

}
2. 前端代码
  • src.utils.common.js
const baseURL = '/api'

// 通用下载方法
export function download(fileName) {
    window.location.href = baseURL + "/common/download?fileName=" + encodeURI(fileName) + "&delete=" + false;
}
  • src.main.js

    全局挂载

import {download} from "./utils/common";

Vue.prototype.download = download
  • 示例
<div class="pull-right">
	<el-link @click="downloadFile(lawDetail.filePath)">{{downloadFilePath.split("/")[1]}}
    </el-link>
</div>
<script>
    data: function () {
        return {
            downloadFilePath: "",
            lawDetail: [],
        }
    },
    export default {
        methods: {
            downloadFile(fileName) {
                this.download(fileName);
            },
        }
	}

参考: 若依后端手册 - 上传下载

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值