Java文件上传与下载

在项目开发中,我们经常要用到文件上传和下载,本章主要介绍一下简单的文件上传和下载功能的实现。

文件上传

因为项目很多地方要用到上传功能,所以抽取出来一个UploadUtils工具类,需要使用文件上传功能只需要注入UploadUtils就行。

项目中配置的额外的静态资源目录,返回的是相对路径(相对于静态资源目录的路径),如/role/a.png表示的是D:/uploads/mhxysy/role/a.png或者项目resources目录下META-INF/resources、public、resources、static下的/role/a.jpg。

application.properties的部分内容:

# 文件上传路径
uploads.path=D:/uploads/mhxysy
# 配置静态资源文件夹,默认是static文件夹
spring.web.resources.static-locations=file:${uploads.path},classpath:static

JsonResult.java代码:

@Data
public class JsonResult<T> {
    /**
     * 响应状态码
     */
    private Integer code;
    /**
     * 响应提示信息
     */
    private String message;
    /**
     * 响应数据
     */
    private T data;


    public static <T> JsonResult<T> success(String message, T data) {
        JsonResult<T> jsonResult = new JsonResult<>();

        jsonResult.setCode(ResponseCode.SUCCESS.getValue());
        jsonResult.setMessage(message);
        jsonResult.setData(data);

        return jsonResult;
    }

    // 省略的其他代码...

}

UploadUtils.java

import cn.edu.sgu.www.mhxysy.restful.ResponseCode;
import cn.edu.sgu.www.mhxysy.exception.GlobalException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;

/**
 * 文件上传工具类
 */
@Component
public class UploadUtils {
    /**
     * 文件上传根路径
     */
    @Value("${uploads.path}")
    private String root;

    public String getRoot() {
        return root;
    }

    /**
     * 图片上传
     * @param file MultipartFile对象
     * @param directory 文件上传目录
     * @return JsonResult<String>
     */
    public String upload(MultipartFile file, String directory) throws IOException {
        boolean result = check(file);

        if (result) {
            // 获取文件名
            String fileName = StringUtils.getFileName(file);
            // 创建目标对象
            File targetFile = new File(root + directory, fileName);

            // 保存文件
            file.transferTo(targetFile);

            return directory + "/" + fileName;
        }

        return null;
    }

    /**
     * 检查文件格式
     * @param file MultipartFile
     */
    private boolean check(MultipartFile file) {
        if (file == null) {
            throw new GlobalException(ResponseCode.BAD_REQUEST, "您未上传任何图片!");
        }

        String filename = file.getOriginalFilename();
        String fileType = StringUtils.getFileType(filename).toLowerCase();

        // 图片文件名后缀
        String picPrefix = ".webp,.jpeg,.jpg,.png";

        if (!picPrefix.contains(fileType)) {
            throw new GlobalException(ResponseCode.BAD_REQUEST, "只允许上传格式为" + picPrefix + "的图片");
        }

        return true;
    }

}

StringUtils.java

package cn.edu.sgu.www.mhxysy.util;

import org.springframework.web.multipart.MultipartFile;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

/**
 * String工具类
 */
public class StringUtils {
    /**
     * 根据当前时间生成UUID
     * @return String
     */
    public static String uuid() {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
        LocalDateTime localDate = LocalDateTime.now();

        return localDate.format(formatter);
    }

    /**
     * 通过文件名获取文件类型
     * @param fileName 文件名
     */
    public static String getFileType(String fileName) {
        // 得到文件名中最后一次出现"."的位置
        int index = fileName.lastIndexOf('.');

        // 文件类型统一转换为小写
        return fileName.substring(index).toLowerCase();
    }

    /**
     * 获取文件名
     * @param filename String
     * @return String 由当前时间生成的新文件名
     */
    public static String getFileName(String filename) {
        // 返回uuid.文件类型,如:20220618131456.jpg
        return uuid() + getFileType(filename);
    }

    /**
     * 获取文件名
     * @param file MultipartFile对象
     * @return String 由当前时间生成的新文件名
     */
    public static String getFileName(MultipartFile file) {
        // 得到上传文件的原始文件名
        String filename = file.getOriginalFilename();

        // 判断文件名是否为空
        if (isNullOrEmpty(filename)) {
            throw new RuntimeException("获取文件名失败!");
        }

        // 返回uuid.文件类型,如:20220618131456.jpg
        return uuid() + getFileType(filename);
    }

}

文件下载

@Slf4j
@RestController
@RequestMapping(path = "/song", produces="application/json; charset=utf-8")
public class SongController {
    /**
     * 下载歌曲
     * @param id 歌曲id
     * @param url 歌曲文件URL
     * @param response HttpServletResponse对象
     * @throws IOException read()和write()方法抛出的异常
     */
    @RequestMapping(value = "/download", method = RequestMethod.GET)
    public void download(String id, String url, HttpServletResponse response) throws IOException {
        FileInputStream fis = null;
        OutputStream os = null;
        Song song = service.selectById(id);

        // 下载的歌曲文件名
        String name = song.getSinger() + " - " + song.getName() + StringUtils.getFileType(url);

        try {
            // 创建File对象
            File file = new File(root, url);

            log.debug("下载文件名:{}", file);

            if (file.isFile()) {
                // 设置内容类型
                response.setContentType("application/octet-stream");
                // 支持中文名称文件,需要对header进行单独设置,不然下载的文件名会出现乱码或者无法显示的情况
                String fileName = new String(name.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1);
                // 设置响应头,控制浏览器下载该文件
                response.setHeader("Content-Disposition", "attachement;filename=" + fileName);

                fis = new FileInputStream(file); // 读取文件
                os = response.getOutputStream(); // 创建文件输出流对象

                int len;
                byte[] buf = new byte[1024];

                while ((len = fis.read(buf)) != -1) {
                    os.write(buf, 0, len);
                }
            } else {
               log.debug("文件不存在,下载失败···");
            }
        } finally {
            if (fis != null) {
                fis.close();
            }
            if (os != null) {
                os.close();
            }
        }
    }
}

好了,文章就分享到这里了,感谢阅读~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值