springboot上传与下载文件[记录]

55 阅读3分钟

文件sql:

CREATE TABLE `document_file` (
  `id` int NOT NULL AUTO_INCREMENT,
  `bussiness_id` varchar(168) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '业务id',
  `domain` varchar(200) DEFAULT '' COMMENT '主目录',
  `file_name` varchar(200) DEFAULT '' COMMENT '原文件名',
  `file_suffix` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT '' COMMENT '文件后缀',
  `name` varchar(100) DEFAULT '' COMMENT '系统文件名',
  `path` varchar(100) DEFAULT '' COMMENT '路径',
  `path_ext` varchar(100) DEFAULT '' COMMENT '扩展目录',
  `size` bigint DEFAULT '0' COMMENT '文件大小',
  `delete_flg` tinyint DEFAULT '0' COMMENT '删除标记 0 未删除 1 删除',
  `create_user_id` int DEFAULT '0' COMMENT '创建人id',
  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  PRIMARY KEY (`id`,`bussiness_id`) USING BTREE,
  KEY `del_code` (`delete_flg`,`bussiness_id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8mb3 COMMENT='文档文件';

实体类:


import lombok.*;
import tk.mybatis.mapper.annotation.KeySql;

import javax.persistence.Column;
import javax.persistence.Id;
import javax.persistence.Table;
import java.io.Serializable;

@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Table(name = "document_file")
public class Attachment implements Serializable {

    private static final long serialVersionUID = 6295975348974510001L;

    @Id
    @KeySql(useGeneratedKeys = true)
    private Integer id;

    // 业务id
    @Column(name = "bussiness_id")
    private String bussinessId;

    // 主目录
    @Column(name = "domain")
    private String domain;

    // 原文件名
    @Column(name = "file_name")
    private String fileName;

    // 系统文件名
    @Column(name = "name")
    private String name;

    // 文件名后缀
    @Column(name = "file_suffix")
    private String fileSuffix;

    // 路径
    @Column(name = "path")
    private String path;

    // 扩展目录
    @Column(name = "path_ext")
    private String pathExt;

    // 文件大小
    @Column(name = "size")
    private Long size;

    // 是否删除
    @Column(name = "delete_flg")
    private Integer deleteFlg;

    // 创建人id
    @Column(name = "create_user_id")
    private Integer createUserId;

    // 创建时间
    @Column(name = "create_time")
    private String createTime;

}

先来2个参数:

String PATH = "img/st/";
String LOCAL_HOST = "http://localhost:8888/";

上传文件的service层:


// 上传附件
public Integer uploadFile(MultipartFile multipartFile, String bussinessId, Op op) throws IOException {
    String LOCAL_HOST = sysConfigService.getValueByKey(CacheKeyConstant.LOCAL_HOST);
    String uuid = UUID.randomUUID().toString();
    if(StrUtil.isBlank(bussinessId)){
        bussinessId = uuid;
    }
    Assert.isTrue(!multipartFile.isEmpty(),"上传文件为空");
    Attachment uploadFile = new Attachment();
    // 保存原文件名称,文件列表展示需要用到
    String fileName = multipartFile.getOriginalFilename();
    uploadFile.setFileName(fileName);
    // 生成系统文件名称,不可重复,防止同名文件上传覆盖问题
    String fileSuffix = multipartFile.getOriginalFilename().substring(multipartFile.getOriginalFilename().lastIndexOf(".")).toLowerCase();
    String fileType = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();
    // 判定传递的类型
    Assert.isTrue(isUploadType(fileType),"目前只支持:"bmp", "jpg", "jpeg", "png", "gif"");
    String name = bussinessId + DateUtil.format(new Date(), "yyyyMMddHHmmss");
    uploadFile.setName(name);
    uploadFile.setFileSuffix(fileSuffix);
    // 判断文件类型
    uploadFile.setDomain(LOCAL_HOST + PATH);
    //这种方式比类型强转效率更高
    String pathExt = System.currentTimeMillis()+"";
    uploadFile.setPath(LOCAL_HOST + PATH + pathExt);
    uploadFile.setPathExt(pathExt);
    // 获取文件大小
    uploadFile.setSize(multipartFile.getSize());
    uploadFile.setBussinessId(bussinessId);

    uploadFile.setCreateTime(DateUtil.now());
    uploadFile.setDeleteFlg(DataConstant.DELETE_FLAG);
    uploadFile.setCreateUserId(op.getOpUserId());

    // 将文件保存到本目录/resources/files/下
    // DateUtil.today()得到得是当天日期如:20230715,这个会在/resources/files/下再以日期生成一层目录
    String filePath = Paths.get("").toAbsolutePath().normalize().toString(); // 获取当前JAR文件所在目录的绝对路径
    File newFile = new File(filePath + "/" + PATH + pathExt +  "/" + name + fileSuffix);
    // 保证这个文件的父文件夹必须要存在
    if (!newFile.getParentFile().exists()) {
        newFile.getParentFile().mkdirs();
    }
    newFile.createNewFile();
    // 将文件内容写入到这个文件中
    InputStream is = multipartFile.getInputStream();
    FileOutputStream fos = new FileOutputStream(newFile);
    try {
        int len;
        byte[] buf = new byte[1024];
        while ((len = is.read(buf)) != -1) {
            fos.write(buf, 0, len);
        }
    }catch (Exception e){
        return -1;
    }finally {
        // 关流顺序,先打开的后关闭
        fos.close();
        is.close();
    }
    attachmentDao.insert(uploadFile);
    return uploadFile.getId();
}
public boolean isUploadType(String fileType){
    String img[] = {"bmp", "jpg", "jpeg", "png", "gif"};
    for (int i = 0; i < img.length; i++) {
       if(img[i].equals(fileType)) return true;
    }
    return false;
}

下载文件的service:

public void showPhoto(HttpServletResponse response, Integer id){
    Attachment attachment = Attachment.builder().build();
    if(id != null){
        attachment = attachmentDao.selectByPrimaryKey(id);
    }
    String filePath = Paths.get("").toAbsolutePath().normalize().toString(); // 获取当前JAR文件所在目录的绝对路径
    String showPath = filePath + "/" + PATH + attachment.getPathExt() +  "/" + attachment.getName()
            + attachment.getFileSuffix();
    // 去./resources/files/目录下取出文件
    log.error("showPathshowPathshowPathshowPathshowPath=" + showPath);
    File downloadFile = new File(showPath);
    Assert.isTrue(downloadFile.exists(),"查询文件为空");
    Assert.isTrue(downloadFile.length() != 0,"文件没东西");

    InputStream is = null;
    OutputStream os = null;
    try {
        // 判断是否是图片,如果是图片加上 response.setContentType("image/jpeg"),这样就可以直接在浏览器打开而不是下载
        response.setContentType("image/jpeg");
        
        response.addHeader("Content-Length", "" + downloadFile.length());
        is = new FileInputStream(downloadFile);
        os = response.getOutputStream();
        IOUtils.copy(is, os);
    } catch (Exception e) {
        log.error("展示图片发生异常", e);
    } finally {
        try {
            if (os != null) {
                os.flush();
                os.close();
            }
            if (is != null) {
                is.close();
            }
        } catch (IOException e) {
            log.error("关闭流发生异常", e);
        }
    }
}

web层

// 上传
public Integer uploadFile(@RequestPart("file") MultipartFile file,
                          @RequestParam(required = false) String bussinessId) throws IOException {
    Op op = Op.createOp(TokenCache.getInstance().get());
    return attachmentService.uploadFile(file, bussinessId,op);
}
// 展示
public void showPhoto(HttpServletResponse response,
                     @RequestParam(required = false) Integer id) throws Exception {

    Assert.isTrue(id != null ,"必须传递一个");
    attachmentService.showPhoto(response, id);
}

获取jar内的文件:

InputStream inputStream = Thread.currentThread().getContextClassLoader()
.getResourceAsStream("img/st/.....xlsx");

//拿到项目的文件,转换成文件输入流
ClassPathResource resource = new ClassPathResource("\\templates\\contract-template.ftl");
 //获取文件输入流
InputStream stream = resource.getInputStream();

参考地址: blog.csdn.net/weixin_4588…