SpringBoot框架层封装,实现文件、图片、表单等下载与上传

本博客可实现文件,图片等上传,代码可直接调用service层upload方法,可参考上一篇博客图片实现的简单上传

前言

  • 文件上传下载应用场景很多。比如:我们在修改头像的时候,需要上传头像;我们在后台修改商品信息的时候,也需要上传商品图片。作为Java开发者,文件上传与文件下载功能已经是必会的技能。
  • 这次使用SpringBoot实现单文件上传,多文件上传以及文件下载,重点介绍MultipartFile工具类。

文件上传到哪里合适?

  • 将文件上传到工程目录下:在一些文件存储量很小的工程中,有一些上传文件放置在工程本身的目录下,但是随着文件上传的量越来越大,工程本身所在的文件夹容量会越来越大,不仅打包和部署的效率会降低,工程的启动和运行也会变慢,所以一般不会采用这做

  • 将文件上传到工程所在服务器:将文件专门上传到Web应用工程所在容器(如Tomcat)位于的服务器中,单独开辟一个盘符或文件夹用于存储上传的图片,这种做法让上传 文件与工程本身分离,工程的打包和启动效率不受到任何影响。但是如果以后出现了海量图片,Web应用工程所在的服务器的效率会降低,这样也会间接地降低应用的执行效率,所以在上传图片量不大的情况下,可以采用该做法。

  • 搭建文件服务器:一般大型的互联网项目,都会为自己的文件上传单独架设一个文件服务器(有集群的应用,可能会有多台文件服务器),也有独立处理文件上传、文件访问的服务器。这种方案就是太烧钱。

上面分析了三种方案的特点和优缺点。第一种一般不采取,第二种可能会采取,最常用的就是第三种方案。

MultipartFile工具类

MultipartFile是SpringMVC提供简化上传操作的工具类。
在不使用框架之前,都是使用原生的HttpServletRequest来接收上传的数据,文件是以二进制流传递到后端的,然后需要我们自己转换为File类,非常麻烦。使用了MultipartFile工具类之后,我们对文件上传的操作就简便许多了。

以下是MultipartFile的框架层面的封装

controller层

package *.controller;

import *.framework.web.message.MessageBody;
import *.framework.web.message.MessageCode;
import *.framework.web.upload.model.UploadRequest;
import *.framework.web.upload.properties.UploadProperties;
import *.framework.web.upload.service.IUploadService;
import *.framework.web.upload.utils.UploadUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.*;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.nio.charset.Charset;

/**
 * 上传文件基础类
 */
@Slf4j
public abstract class AbstractUploadController {
   
    @Autowired
    protected IUploadService uploadService;
    @Autowired
    private UploadProperties uploadProperties;


    /**
     * 预上传,返回上传所需参数
     *
     * @param uploadRequest 上传请求
     * @return httpResponse
     */
    @GetMapping("/upload/preload")
    public MessageBody<?> preload(UploadRequest uploadRequest) {
   
        return MessageCode.SUCCESS.data(uploadService.preload(uploadRequest));
    }

    /**
     * 上传文件
     *
     * @param uploadFile    文件
     * @param uploadRequest 上传请求
     * @param token         签名字符串
     * @return httpResponse
     */
    @PostMapping("/upload")
    public MessageBody<?> upload(@RequestParam("file") MultipartFile uploadFile, UploadRequest uploadRequest, String token) {
   
        try {
   
            //判断是否需要限制
            if (uploadProperties.getFileTypeLimit() != null && uploadProperties.getFileTypeLimit().size() > 0

            ) {
   
                //检验上传文件类型是否支持
                if (!UploadUtils.checkType(uploadProperties.getFileTypeLimit(), uploadFile)) {
   
                    return MessageCode.ERROR.message("上传文件类型不支持");
                }
                //检验上传文件大小是否支持
                if (!UploadUtils.checkLimit(uploadProperties.getFileTypeLimit(), uploadFile)) {
   
                    return MessageCode.ERROR.message("上传文件大小超出限制");
                }
            }
            return MessageCode.SUCCESS.data(uploadService.upload(uploadFile, uploadRequest, token));
        } catch (IOException e) {
   
            return MessageCode.ERROR.build();
        }
    }


    /**
     * 预览、下载上传的文件
     *
     * @param fileName 文件名称
     * @return 文件流
     */
    @GetMapping("/media/{fileName}/_download")
    public ResponseEntity<?> download(@PathVariable String fileName) {
   
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
        Charset charset = Charset.defaultCharset();
        headers.setContentDisposition(ContentDisposition.builder("attachment").filename(fileName, charset).build());
        return new ResponseEntity<>(uploadService.files(fileName), headers, HttpStatus.OK);
    }
}

上传请求实体类

package *.web.upload.model;

import lombok.Data;
@Data
public class UploadRequest {
   
    /**
     * 是否覆盖 0.否 1.是
     */
    private Integer isCover = 1;

    /**
     * 要存储的文件名称
     */
    private String fileName;

    /**
     * 时间戳
     */
    private long timestamp;

}

签名

@Data
@AllArgsConstructor
public class UploadToken {
   
    private String sign;
    private Long timestamp;
}

service层,抽象类

package*.web.upload.service;

import *
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;


public abstract class IUploadService {
   
    protected static final DateTimeFormatter FILE_NAME_FORMATTER = DateTimeFormatter.ofPattern("yyyyMMddHHmmssSS");

    protected IUploadService() {
   
    }

    /**
     * 预上传,获取token
     *
     * @param uploadRequest 上传请求实体
     * @return 签名
     */
    public abstract UploadToken preload(UploadRequest uploadRequest);

    /**
     * 通过multipartFile上传文件,无token
     *
     * @param uploadFile    文件
     * @param uploadRequest 请求实体
     * @return 上传成功实体
     * @throws IOException ioexception
     */
    public UploadSuccess upload(MultipartFile uploadFile, UploadRequest uploadRequest) throws IOException {
   
        return this.upload(uploadFile, uploadRequest, null);
    }

    /**
     * 通过multipartFile上传文件,有token
     *
     * @param uploadFile    文件
     * @param uploadRequest 请求实体
     * @param token         签名字符串
     * @return 上传成功实体
     * @throws IOException ioexception
     */
    public abstract UploadSuccess upload(MultipartFile uploadFile, UploadRequest uploadRequest, String token) throws IOException;


    /**
     * 通过stream上传文件,无token
     *
     * @param uploadStream  文件流
     * @param uploadRequest 请求实体
     * @return 上传成功实体
     * @throws IOException ioexception
     */
    public UploadSuccess upload(InputStream uploadStream, UploadRequest uploadRequest) throws IOException {
   
        return this.upload(uploadStream, uploadRequest, null);
    }

    /**
     * 通过stream上传文件,有token
     *
     * @param uploadStream  上传的stream流
     * @param uploadRequest 请求实体
     * @param token         签名字符串
     * @return 上传成功实体
     * @throws IOException ioexception
     */
    public abstract UploadSuccess upload(InputStream uploadStream, UploadRequest uploadRequest, String token) throws IOException;

    /**
     * 通过字节数组上传文件,无token
     *
     * @param uploadByte    字节数组
     * @param uploadRequest 请求实体
     * @return 上传成功实体
     * @throws IOException ioexception
     */
    public UploadSuccess upload(byte[] uploadByte, UploadRequest uploadRequest) throws IOException {
   
        return this.upload(uploadByte, uploadRequest, null);
    }

    /**
     * 通过字节数组上传文件,有token
     *
     * @param uploadByte    上传的字节数组
     * @param uploadRequest 请求实体
     * @param token         签名字符串
     * @return 上传成功实体
     * @throws IOException ioexception
     */
    public abstract UploadSuccess upload(byte[] uploadByte, UploadRequest uploadRequest, String token) throws IOException;

    /**
     * 根据上传参数获取文件名称
     *
     * @param uploadRequest 上传参数
     * @return 文件名
     */
    protected String getFileName(UploadRequest uploadRequest, MultipartFile multipartFile) {
   
        String suffix = multipartFile != null ? Utils.fileSuffixWithPoint(multipartFile
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值