Java文件上传与下载

发布时间 2023-12-13 13:56:41作者: Xproer-松鼠

文件上传
因为项目很多地方要用到上传功能,所以抽取出来一个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();
}
}
}
}

 

参考文章:http://blog.ncmem.com/wordpress/2023/12/13/java%e6%96%87%e4%bb%b6%e4%b8%8a%e4%bc%a0%e4%b8%8e%e4%b8%8b%e8%bd%bd/

欢迎入群一起讨论