JAVA文件上传与下载

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

JAVA文件上传与下载

前言

在实际项目开发中,涉及到图片、视频、文档等上传与下载的情况十分普遍,本文就简单介绍文件上传下载的相关内容。


提示:以下是本篇文章正文内容,下面案例可供参考

一、文件上传

文件上传接口接收了前端传过来文件,需要把文件存储在本地,另一方面存储在数据库文件表中,最后将文件表中的文件ID返回给前端,前端就可以拿着文件ID走业务的新增、修改接口,将文件数据和业务数据进行绑定。
文件表建表语句(mysql):

 DROP TABLE IF EXISTS T_FILE;
 CREATE TABLE T_FILE(
    ID VARCHAR(32) NOT NULL   COMMENT '主键' ,
    FILE_NAME VARCHAR(32)    COMMENT '文件名' ,
    CONTENT VARCHAR(32)    COMMENT '远程文件id' ,
    ENTITY_ID VARCHAR(32)    COMMENT '对应id' ,
    ENTITY_TYPE INT    COMMENT '文件类型' ,
    TYPE VARCHAR(32)    COMMENT '文件后缀' ,
    SHOW_INDEX INT    COMMENT '显示顺序' ,
    CREATED_BY VARCHAR(32)    COMMENT '创建人' ,
    CREATED_TIME DATETIME    COMMENT '创建时间' ,
    UPDATED_BY VARCHAR(32)    COMMENT '更新人' ,
    UPDATED_TIME DATETIME    COMMENT '更新时间' ,
    PRIMARY KEY (ID)
)  COMMENT = '文件表';
代码如下:
控制层代码:
@PostMapping("/upload")
@ApiOperation(value = "文件上传"")
@ResponseBody
public BaseResponse uploadFile(@RequestPart("file") MultipartFile multipartFile) {
    try {
        return uploadFileService.upload(multipartFile);
    } catch (Exception e) {
        e.printStackTrace();
        throw new BusinessException(e.getMessage());
    }
}

ServiceImpl代码

 /**
     * 上传文件
     *
     * @param multipartFile
     * @return
     * @throws Exception
     */
    @Override
    public BaseResponse upload(MultipartFile multipartFile) throws Exception {
        if (multipartFile == null) {
            log.error("Please choose an image to upload..");
            return BaseResponse.getFail("Please choose an image to upload..");
        }
        String originalFilename = multipartFile.getOriginalFilename();
        FileResponse fileResponse = new FileResponse();
        String fileUUID = saveFileToLocal(multipartFile);
        fileResponse.setId(fileUUID);
        fileResponse.setFileName(originalFilename);
        return BaseResponse.getSuccess(fileResponse);
    }
/**
     * 上传到本地文件
     *
     * @param multipartFile
     * @return
     */
    private String saveFileToLocal(MultipartFile multipartFile) {
        File databaseDir = new File(databasePath);
        if (!databaseDir.exists()) {
            databaseDir.mkdir();
        }
        String fileUUID = UUID.randomUUID().toString().toLowerCase().replace("-", "");
        String fileType = multipartFile.getOriginalFilename().substring(multipartFile.getOriginalFilename().lastIndexOf(".") + 1);
        try (FileOutputStream fileOutputStream = new FileOutputStream(databasePath + "/" + fileUUID + "." + fileType)) {
            org.apache.commons.io.IOUtils.copy(multipartFile.getInputStream(), fileOutputStream);
            FileEntity fileEntity = new FileEntity();
            fileEntity.setId(fileUUID);
            fileEntity.setFileName(multipartFile.getOriginalFilename());
            fileEntity.setContent(fileUUID);
            fileEntity.setType(fileType);
            fileEntity.setCreatedTime(DateUtils.getCurrentTime());
            fileEntity.setCreatedBy(jwtUtils.getUserId());
            save(fileEntity);
            return fileUUID;
        } catch (FileNotFoundException e) {
            log.error(e.getMessage(), e);
        } catch (IOException e) {
            log.error(e.getMessage(), e);
        }
        return null;
    }

二、文件下载

将文件上传返回的文件ID传入,将文件数据以流的方式进行返回
控制层代码

@GettMapping("/download")
@ApiOperation( "文件下载")
@ResponseBody
public void downloadFile(String fileUUID, HttpServletResponse response) {
    try {
        uploadFileService.downloadFile(fileUUID, response);
    } catch (Exception e) {
        throw new BusinessException(e.getMessage());
    }
}

serviceImpl代码

/**
     * 下载文件
     *
     * @param fileUUID
     * @param response
     * @throws Exception
     */
    @Override
    public void downloadFile(String fileUUID, HttpServletResponse response) throws Exception {
        InputStream inputStream = null;
        try {
            FileEntity fileEntity = getById(fileUUID);
            if (fileEntity == null) {
                throw new BusinessException("Can't find file info by fileUUID:" + fileUUID);
            }

            response.setCharacterEncoding("UTF-8");
            response.setHeader("content-Type", "application/octet-stream");
            response.setHeader("Content-Disposition", "attachment;filename=" + fileEntity.getFileName());
            OutputStream outputStream = response.getOutputStream();
            inputStream = downloadFileByLocalUUID(fileEntity);
            IOUtils.copy(inputStream, outputStream);
        } finally {
            IOUtils.closeQuietly(inputStream);
        }
    }
 /**
     * 从本地下载文件
     *
     * @param fileEntity
     * @return
     */
    private InputStream downloadFileByLocalUUID(FileEntity fileEntity) {
        try {
            String filePath = databasePath + "/" + fileEntity.getContent() + "." + fileEntity.getType();
            File file = new File(filePath);
            if (file.exists()) {
                return new FileInputStream(file);
            } else {
                throw new BusinessException("Can't fild the file: " + file.getAbsolutePath());
            }
        } catch (Exception e) {
            throw new BusinessException("Download file error:" + e.toString());
        }
    }

拓展

当数据库存储与文件相关内容时,有两种做法,一则是通过上述方式通过业务ID和业务类型将业务和文件查询出来,二则是直接业务表中直接存储url,在文件表中维护具体的信息,这两种方式各有优劣。
直接存储URL:
优点:简单易用;减少查询次数;易于维护(存储位置不变)
缺点:安全性较低;URL变更困难(全路径);冗余问题
业务ID和业务类型:
优点:灵活性高;安全性高;便于扩展(额外的标签信息)
缺点:增加复杂性(查询次数);性能开销
结论:如果项目较小,对安全性和灵活性要求不高,直接存储URL更为合适;对于大型项目,对安全性、灵活性要求比较高,可以用存储ID的方式

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值