适用 spring mvc, spring boot
Controller代码:
@PostMapping("/files")
@ResponseStatus(HttpStatus.CREATED)
public List<String> handleFileUpload(@RequestParam("files") MultipartFile[] files, String dir) {
//获取项目当前路径
String projectFolder = System.getProperty("user.dir");
List<String> publicPathList = Lists.newArrayList();
for (MultipartFile file : files) {
//根据需求提供上传路径
String publicPath = "/upload/" + dir + "/" + file.getOriginalFilename();
File realFile = new File(projectFolder + publicPath);
file.transferTo(realFile);
publicPathList.add(publicPath);
}
return publicPathList;
}
html代码:
<form action="/files" method="post" encType="multipart/form-data">
<!--注意accept属性不要写成*/*,会卡成翔,根据需求写对应的mime,别偷懒-->
<input type="file" name="files" multiple="multiple" accept="image/jpg,image/jpeg,image/png" />
<!--和文件一起提交别的参数-->
<input type="hidden" name="dir" value="avatar" />
</form>
文件处理 :
可以利用MultipartFile的getInputStream方法对文件进一步处理,举个栗子,图片压缩:
//使用阿里的图片处理库:SimpleImage
private void scale(InputStream inputStream, FileOutputStream outputStream) throws SimpleImageException{
//这里默认最大宽度1024,最大高度1024了,可根据需求做成参数
ScaleParameter scaleParam = new ScaleParameter(1024,1024);
WriteParameter writeParam = new WriteParameter();
ImageRender rr = new ReadRender(inputStream);
ImageRender sr = new ScaleRender(rr, scaleParam);
ImageRender wr = null;
try {
wr = new WriteRender(sr, outputStream, ImageFormat.JPEG, writeParam);
wr.render();
} catch (SimpleImageException e) {
throw e;
} finally {
IOUtils.closeQuietly(inputStream);
IOUtils.closeQuietly(outputStream);
try {
if (wr != null) {
wr.dispose();
}
} catch (SimpleImageException e) {
// ignore ...
}
}
}
调用
scale(file.getInputStream(), new FileOutputStream(realFile));
踩坑
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>simpleimage</artifactId>
<version>1.2.3</version>
<!--使用spring boot时会和默认引入的log4j-over-slf4j冲突,需要干掉-->
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--SimpleImage依赖的javax.media.jai.core在官方的maven仓库中并没有,需要引用spring提供的-->
<dependency>
<groupId>javax.media.jai</groupId>
<artifactId>com.springsource.javax.media.jai.core</artifactId>
<version>1.1.3</version>
</dependency>
代码组织:
建议将文件上传处理部分抽出来,如:
FileService //文件处理接口
LocalFileServiceImpl //本地存储文件处理实现
QiniuFileServiceImpl //七牛云存储文件处理实现
上传路径和可访问路径可放到配置文件中,贴下spring-boot环境完整本地文件处理实现供参考:
LocalFileServiceImpl
@Service
public class LocalFileServiceImpl implements FileService {
@Resource
private UploadProperties uploadProperties;
@Override
public String upload(MultipartFile file, String dir, int maxWidth, int maxHeight) throws Exception {
String projectFolder = System.getProperty("user.dir");
String folderAndName = getFileUriGeneratedPart(file, dir);
String path = projectFolder + uploadProperties.getPath() + folderAndName;
File realFile = new File(path);
if(!realFile.getParentFile().exists()) {
if(!realFile.getParentFile().mkdirs()) {
throw new Exception("创建文件上传目录失败");
}
}
try {
scale(file.getInputStream(), new FileOutputStream(realFile), maxWidth, maxHeight);
} catch (Exception e) {
throw new Exception(e.getMessage());
}
return uploadProperties.getPublicPath() + folderAndName;
}
private String getFileUriGeneratedPart(MultipartFile file, String dir) {
return "/" + dir + "/"+ genRandomString(16) +
"." + getExtensionName(file.getOriginalFilename());
}
//缩放用户上传图片,减小宽带占用
private void scale(InputStream inputStream, FileOutputStream outputStream, int maxWidth, int maxHeight) throws SimpleImageException{
ScaleParameter scaleParam = new ScaleParameter(maxWidth, maxHeight);
WriteParameter writeParam = new WriteParameter();
ImageRender rr = new ReadRender(inputStream);
ImageRender sr = new ScaleRender(rr, scaleParam);
ImageRender wr = null;
try {
wr = new WriteRender(sr, outputStream, ImageFormat.JPEG, writeParam);
wr.render();
} catch (SimpleImageException e) {
throw e;
} finally {
IOUtils.closeQuietly(inputStream);
IOUtils.closeQuietly(outputStream);
try {
if (wr != null) {
wr.dispose();
}
} catch (SimpleImageException e) {
// ignore ...
}
}
}
private static String getExtensionName(String filename) {
if (StringUtils.isNotBlank(filename)) {
int dot = filename.lastIndexOf('.');
if ((dot >-1) && (dot < (filename.length() - 1))) {
return filename.substring(dot + 1).toLowerCase();
}
}
return filename;
}
private static String genRandomString(int length) {
String base = "abcdefghijklmnopqrstuvwxyz0123456789";
Random random = new Random();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < length; i++) {
int number = random.nextInt(base.length());
sb.append(base.charAt(number));
}
return sb.toString();
}
}
以上代码移除了自定义的异常类
UploadProperties
@Component
@ConfigurationProperties("custom.upload")
public class UploadProperties {
private String path;
private String publicPath;
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public String getPublicPath() {
return publicPath;
}
public void setPublicPath(String publicPath) {
this.publicPath = publicPath;
}
}
spring boot配置 application-local.yml
custom.upload:
path: /src/upload
public-path: /upload