提示:本文仅记录本人工作中遇到的难点与个人见解,仅供参考,如有问题请见谅。
目录
前言
文件上传,也称为upload,是指将本地图片、视频、音频等文件上传到服务器上,以供用户预览或下载。
一、创建UploadUtil工具类
代码如下:
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.util.CommonUtils;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
/**
* 该类处理文件的上传(图片、PDF、视频)
*/
@Slf4j
public class UploadUtil {
/**
* Web端上传文件工具类:返回图片、文件、视频的保存路径
* @param multipartFile 文件
* @param path 保存路径(图片、电子书、视频的保存路径是不一致的)
* @param kind 上传文件的种类;图片填"images",pdf填"pdf",视频填"video"
*/
public static String upload(MultipartFile multipartFile, String path, String kind) {
try {
// 先创建文件夹,例如 E://upload//images或者/opt/yhs/images
File file = new File(path + File.separator);
if (!file.exists()) {
file.mkdirs();
}
// 文件原始名(包括后缀);例如123456.txt
String orgName = multipartFile.getOriginalFilename();
// 不包括后缀的文件名;例如123456
String preName = orgName.substring(0, orgName.lastIndexOf("."));
// 如果文件名太长,则只截取文件名前15位字符+后缀,再拼接时间戳进行返回并保存
if (preName.length() > 15) {
orgName = preName.substring(0, 15) + orgName.substring(orgName.lastIndexOf("."));
}
// 判断文件名是否带盘符并重新处理
orgName = CommonUtils.getFileName(orgName);
// 生成的新文件名
String fileName;
if (orgName.contains(".")) {
// 示例:test.123456.png,经过处理后得到:test.123456_1661136943533.png
fileName = orgName.substring(0, orgName.lastIndexOf(".")) + "_" + System.currentTimeMillis() + orgName.substring(orgName.lastIndexOf("."));
} else {
// 文件名中没有"."说明这不是一个正常的文件
return "";
}
// 将用户上传的文件复制到指定目录
String savePath = file.getPath() + File.separator + fileName;
File saveFile = new File(savePath);
FileCopyUtils.copy(multipartFile.getBytes(), saveFile);
// 返回给前端的具体完整地址
String dbPath = "";
// 获取系统类型(Win和Linux返回的路径是不一样的)
String osName = System.getProperty("os.name");
if (osName.startsWith("Windows")) {
// 这是windows系统上的保存路径
switch (kind) {
case "images":
dbPath = "/upload/images" + File.separator + fileName;
break;
case "pdf":
dbPath = "/upload/pdf" + File.separator + fileName;
break;
default:
dbPath = "/upload/video" + File.separator + fileName;
}
} else if (osName.startsWith("Linux")) {
// 这是linux系统上的保存路径
dbPath = file.getPath() + File.separator + fileName;
}
if (dbPath.contains("\\")) {
dbPath = dbPath.replace("\\", "/");
}
// 返回完整目录+文件名,例如/upload/images/aaa.png或者/opt/yhs/images/aaa.png;前端根据项目具体地址拼接即可
return dbPath;
} catch (Exception e) {
log.error(e.getMessage(), e);
}
return "";
}
}
二、需要在yml中定义上传到系统的路径
# 图片保存路径(不管什么图片,全都保存在该目录)
images: E://upload//images
# pdf保存路径
pdf: E://upload//pdf
# 视频保存路径(不管什么视频,全部保存在该目录)
video: E://upload//video
三、创建UploadController
代码如下:
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.modules.util.UploadUtil;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
@Slf4j
@Api(tags = "文件上传和下载")
@RestController
@RequestMapping("/upload")
public class UploadController {
@Value(value = "${jeecg.path.video}")
private String videoPath;
@Value(value = "${jeecg.path.images}")
private String imagesPath;
@Value(value = "${jeecg.path.pdf}")
private String pdfPath;
/**
* 图片上传
*/
@ApiOperation(value = "上传图片接口", notes = "上传图片接口")
@RequestMapping(value = "/uploadImage", method = RequestMethod.POST)
public Result<String> uploadImage(MultipartFile file) {
Result<String> result = new Result<>();
// 图片保存到本地
String savePath = UploadUtil.upload(file, imagesPath, "images");
if (oConvertUtils.isNotEmpty(savePath)) {
result.setResult(savePath);
result.setSuccess(true);
} else {
result.setMessage("上传失败,请稍后再试!");
result.setSuccess(false);
}
return result;
}
/**
* 视频上传(一次上传单个视频)
*/
@ApiOperation(value = "上传视频接口", notes = "上传视频接口")
@RequestMapping(value = "/uploadVideo", method = RequestMethod.POST)
public Result<String> uploadVideo(MultipartFile file) {
Result<String> result = new Result<>();
// 视频保存到本地
String savePath = UploadUtil.upload(file, videoPath, "video");
if (oConvertUtils.isNotEmpty(savePath)) {
result.setResult(savePath);
result.setSuccess(true);
} else {
result.setMessage("上传失败,请稍后再试!");
result.setSuccess(false);
}
return result;
}
/**
* pdf或视频下载统一接口
* @param path 文件保存路径
* @param response 文件流
*/
@ApiOperation(value = "下载文件(视频或pdf)", notes = "下载文件")
@RequestMapping(value = "/downloadFile", method = RequestMethod.GET)
public Result<String> download(@RequestParam(name = "path") String path, HttpServletResponse response) {
Result<String> result = new Result<>();
if (oConvertUtils.isEmpty(path) || path.equals("null")) {
result.setMessage("下载失败,未找到对应文件!");
result.setSuccess(false);
return result;
}
InputStream inputStream = null;
OutputStream outputStream = null;
// 获取文件名
String fileName = path.substring(path.lastIndexOf("/") + 1);
// 拼接出文件的完整路径
String string = bookPath + File.separator + fileName;
try {
string = string.replace("..", "");
if (string.endsWith(",")) {
string = string.substring(0, string.length() - 1);
}
File file = new File(string);
if (!file.exists()) {
result.setMessage("下载失败,文件不存在!");
result.setSuccess(false);
return result;
}
// 设置强制下载不打开(下面这行代码会导致异常,所以暂时注释)
// response.setContentType("application/force-download");
// 设置content-disposition响应头控制浏览器以下载的形式打开文件
response.addHeader("Content-Disposition", "attachment; fileName=" + URLEncoder.encode(fileName, "UTF-8"));
// 获取要下载的文件输入流
inputStream = new BufferedInputStream(new FileInputStream(file));
// 通过response对象获取OutputStream流
outputStream = response.getOutputStream();
// 获取文件长度,前端就可得到下载进度
response.setContentLength((int) file.length());
int length;
// 创建数据缓冲区
byte[] buf = new byte[1024];
while ((length = inputStream.read(buf)) != -1) {
outputStream.write(buf, 0, length);
}
response.flushBuffer();
result.setMessage("下载成功!");
result.setSuccess(true);
} catch (Exception e) {
log.error(e.getMessage(), e);
result.setMessage("下载失败!");
result.setSuccess(false);
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
log.error(e.getMessage(), e);
}
}
if (outputStream != null) {
try {
outputStream.close();
} catch (IOException e) {
log.error(e.getMessage(), e);
}
}
}
return result;
}
}