1.简介
前端代码:
<form action="/upload" method="post" enctype="multipart/form-data">
姓名: <input type="text" name="username"><br>
年龄: <input type="text" name="age"><br>
头像: <input type="file" name="image"><br>
<input type="submit" value="提交">
</form>
MultipartFile 常见方法:
- String getOriginalFilename(); //获取原始文件名
- void transferTo(File dest); //将接收的文件转存到磁盘文件中
- long getSize(); //获取文件的大小,单位:字节
- byte[] getBytes(); //获取文件内容的字节数组
- InputStream getInputStream(); //获取接收到的文件内容的输入流
后端代码:
@Slf4j
@RestController
public class UploadController {
@PostMapping("/upload")
public Result upload(String username, Integer age, MultipartFile image) {
log.info("文件上传:{},{},{}",username,age,image);
return Result.success();
}
}
问题:如果表单项的名字和方法中形参名不一致,该怎么办?
解决:使用@RequestParam注解进行参数绑定
public Result upload(String username, Integer age, @RequestParam("image") MultipartFile file)
当我们程序运行完毕之后,这个临时文件会自动删除。
所以,我们如果想要实现文件上传,需要将这个临时文件,要转存到我们的磁盘目录中。
1.本地存储
保证每次上传文件时文件名都唯一的(使用UUID获取随机文件名)
@Slf4j
@RestController
public class UploadController {
@PostMapping("/upload")
public Result upload(String username, Integer age, MultipartFile image) throws IOException {
log.info("文件上传:{},{},{}",username,age,image);
//获取原始文件名
String originalFilename = image.getOriginalFilename();
//构建新的文件名
String extname = originalFilename.substring(originalFilename.lastIndexOf("."));//文件扩展名
String newFileName = UUID.randomUUID().toString()+extname;//随机名+文件扩展名
//将文件存储在服务器的磁盘目录
image.transferTo(new File("E:/images/"+newFileName));
return Result.success();
}
}
在SpringBoot中,文件上传时默认单个文件最大为1M
如果需要上传大文件,可以在application.properties进行如下配置:
#配置单个文件最大上传大小
spring.servlet.multipart.max-file-size=10MB
#配置单个请求最大上传大小(一次请求可以上传多个文件)
spring.servlet.multipart.max-request-size=100MB
其他方式:
/**
* 文件上传
*/
@RestController
public class FileController {
//绑定文件上传路径到uploadPath
@Value("${web.upload-path}")
private String uploadPath;
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd/");
@PostMapping("/api/file/upload")
public BaseResponse upload(@Param("file") MultipartFile file, HttpServletRequest request) {
BaseResponse response = BaseResponse.successResponse();
DownFileRest rest = new DownFileRest();
String format = sdf.format(new Date());
File folder = new File(uploadPath + format);
if (!folder.isDirectory()) {
folder.mkdirs();
}
// 对上传的文件重命名,避免文件重名
String oldName = file.getOriginalFilename();
String newName = UUID.randomUUID() + oldName.substring(oldName.lastIndexOf("."), oldName.length());
try {
// 文件保存
file.transferTo(new File(folder, newName));
// 返回上传文件的访问路径
String filePath = request.getScheme() + "://" + request.getServerName()
+ ":" + request.getServerPort() +"/"+ format + newName;
System.out.println(filePath);
rest.setFileUrl(filePath);
rest.setName(newName);
} catch (IOException e) {
e.printStackTrace();
}
return response.setData(rest);
}
}
application.yml
spring:
profiles:
active: dev
servlet:
multipart:
# 单个文件的最大值
max-file-size: 100MB
# 传文件总的最大值
max-request-size: 1024MB
jackson:
default-property-inclusion: non_null
mvc:
view:
prefix: /WEB-INF/views/
suffix: .apk
server:
port: 8081
# mybatis-plus
mybatis-plus:
mapper-locations: classpath:**/mapper/*Mapper.xml
application-dev.yml
spring:
datasource:
username: root
password: 123456
url: jdbc:mysql://localhost:3306/demo?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=UTF-8
driver-class-name: com.mysql.cj.jdbc.Driver
web:
resources:
static-locations: classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/,file:${web.upload-path}
server:
port: 8081
logging:
config: classpath:logback.xml
web:
upload-path: G:/data/
2.阿里云OSS
<!--阿里云OSS-->
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
</dependency>
<dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
</dependency>
<!-- no more than 2.3.3-->
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
</dependency>
测试类
import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.PutObjectRequest;
import com.aliyun.oss.model.PutObjectResult;
import java.io.FileInputStream;
import java.io.InputStream;
public class AliOssTest {
public static void main(String[] args) throws Exception {
// Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
String endpoint = "oss-cn-beijing.aliyuncs.com";
// 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
String accessKeyId = "LTAI5tSZXgUGdj6fSGHyPu4T";
String accessKeySecret = "PiBcNmWlZZRRW0yp4E1Q2fSB9gjwEt";
// 填写Bucket名称,例如examplebucket。
String bucketName = "java-web-test-001";
// 填写Object完整路径,完整路径中不能包含Bucket名称,例如exampledir/exampleobject.txt。
String objectName = "1.jpg";
// 填写本地文件的完整路径,例如D:\\localpath\\examplefile.txt。
// 如果未指定本地路径,则默认从示例程序所属项目对应本地路径中上传文件流。
String filePath= "C:\\Users\\Public\\Pictures\\1.jpg";
// 创建OSSClient实例。
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
try {
InputStream inputStream = new FileInputStream(filePath);
// 创建PutObjectRequest对象。
PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, inputStream);
// 设置该属性可以返回response。如果不设置,则返回的response为空。
putObjectRequest.setProcess("true");
// 创建PutObject请求。
PutObjectResult result = ossClient.putObject(putObjectRequest);
// 如果上传成功,则返回200。
System.out.println(result.getResponse().getStatusCode());
} catch (OSSException oe) {
System.out.println("Caught an OSSException, which means your request made it to OSS, "
+ "but was rejected with an error response for some reason.");
System.out.println("Error Message:" + oe.getErrorMessage());
System.out.println("Error Code:" + oe.getErrorCode());
System.out.println("Request ID:" + oe.getRequestId());
System.out.println("Host ID:" + oe.getHostId());
} catch (ClientException ce) {
System.out.println("Caught an ClientException, which means the client encountered "
+ "a serious internal problem while trying to communicate with OSS, "
+ "such as not being able to access the network.");
System.out.println("Error Message:" + ce.getMessage());
} finally {
if (ossClient != null) {
ossClient.shutdown();
}
}
}
}
工具类
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.io.InputStream;
import java.util.UUID;
@Component
public class AliOSSUtils {
@Value("${aliyun.oss.endpoint}")
private String endpoint;
@Value("${aliyun.oss.accessKeyId}")
private String accessKeyId;
@Value("${aliyun.oss.accessKeySecret}")
private String accessKeySecret;
@Value("${aliyun.oss.bucketName}")
private String bucketName;
/**
* 实现上传图片到OSS
*/
public String upload(MultipartFile multipartFile) throws IOException {
// 获取上传的文件的输入流
InputStream inputStream = multipartFile.getInputStream();
// 避免文件覆盖
String originalFilename = multipartFile.getOriginalFilename();
String fileName = null;
if (originalFilename != null) {
fileName = UUID.randomUUID() + originalFilename.substring(originalFilename.lastIndexOf("."));
}
//上传文件到 OSS
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
ossClient.putObject(bucketName, fileName, inputStream);
//文件访问路径
String url = endpoint.split("//")[0] + "//" + bucketName + "." + endpoint.split("//")[1] + "/" + fileName;
// 关闭ossClient
ossClient.shutdown();
return url;// 把上传到oss的路径返回
}
}
aliyun:
oss:
endpoint: https://oss-cn-beijing.aliyuncs.com
accessKeyId: LTAI5txxxxxxxxxxxxxxxxxx
accessKeySecret: PiBcxxxxxxxxxxxxxxxxxxxx
bucketName: java-web-xxxxxxxx
package com.hjy.controller;
import com.hjy.pojo.Result;
import com.hjy.utils.AliOSSUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
import java.util.UUID;
@Slf4j
@RestController
public class UploadController {
@Autowired
private AliOSSUtils aliOSSUtils;
/**
* 上传本地
* @return
* @throws IOException
*/
@PostMapping("/uploadLocal")
public Result uploadLocal(String username, Integer age, MultipartFile image) throws IOException {
log.info("文件上传:{},{},{}",username,age,image);
//获取原始文件名
String originalFilename = image.getOriginalFilename();
//构建新的文件名
String extname = null;//文件扩展名
if (originalFilename != null) {
extname = originalFilename.substring(originalFilename.lastIndexOf("."));
}
String newFileName = UUID.randomUUID() +extname;//随机名+文件扩展名
//将文件存储在服务器的磁盘目录
image.transferTo(new File("E:/images/"+newFileName));
return Result.success();
}
@PostMapping("/upload")
public Result uploadOSS(MultipartFile image) throws IOException {
//调用阿里云OSS工具类,将上传上来的文件存入阿里云
String url = aliOSSUtils.upload(image);
//将图片上传完成后的url返回,用于浏览器回显展示
return Result.success(url);
}
}
其他方法:
@Data
@Component
@ConfigurationProperties(prefix = "aliyun.oss.file")
public class OssProperties {
private String endPoint;
private String keyId;
private String keySecret;
private String bucketName;
}
import org.springframework.web.multipart.MultipartFile;
public interface FileService {
/**
* 删除文件
*
* @param url
*/
void deleteFile(String url);
/**
* 文件上传
*
* @param file 文件上传对象
* @param module 文件夹名称
* @return
*/
String upload(MultipartFile file, String module);
}
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.hjy.config.oss.OssProperties;
import com.hjy.service.FileService;
import org.apache.commons.io.FilenameUtils;
import org.joda.time.DateTime;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import java.io.IOException;
import java.io.InputStream;
import java.util.UUID;
@Service
@Transactional
public class FileServiceImpl implements FileService {
/**
* 文件上传
*
* @param file 文件上传对象
* @param module 文件夹名称
* @return
*/
@Resource
private OssProperties ossProperties;
/**
* 文件上传
*
* @param file 文件上传对象
* @param module 文件夹名称
* @return
*/
@Override
public String upload(MultipartFile file, String module) {
//获取地域节点
String endPoint = ossProperties.getEndPoint();
//获取AccessKeyId
String keyId = ossProperties.getKeyId();
//获取AccessKeySecret
String keySecret = ossProperties.getKeySecret();
//获取BucketName
String bucketName = ossProperties.getBucketName();
try {
//创建OSSClient实例
OSS ossClient = new OSSClientBuilder().build(endPoint, keyId, keySecret);
//上传文件流
InputStream inputStream = file.getInputStream();
//获取旧名称
String originalFilename = file.getOriginalFilename();
//获取文件后缀名
String extension = FilenameUtils.getExtension(originalFilename);
//将文件名重命名
String newFileName = UUID.randomUUID().toString().replace("-", "") + "." + extension;
//使用当前日期进行分类管理
String datePath = new DateTime().toString("yyyy/MM/dd");
//构建文件名
newFileName = module + "/" + datePath + "/" + newFileName;
//调用OSS文件上传的方法
ossClient.putObject(bucketName, newFileName, inputStream);
//关闭OSSClient
ossClient.shutdown();
//返回文件地址
//endPoint---https://oss-cn-beijing.aliyuncs.com
//bucketName---java-web-test-001
return "https://" + bucketName + "." + endPoint.split("//")[1] + "/" + newFileName;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
@Override
public void deleteFile(String url) {
//https://java-web-test-001.oss-cn-beijing.aliyuncs.com/avatar/2024/06/15/20aaa46600364de78bcd1637f146c103.jpg
//获取地域节点
String endPoint = ossProperties.getEndPoint();
//获取AccessKeyId
String keyId = ossProperties.getKeyId();
//获取AccessKeySecret
String keySecret = ossProperties.getKeySecret();
//获取BucketName
String bucketName = ossProperties.getBucketName();
try {
//创建OSSClient实例
OSS ossClient = new OSSClientBuilder().build(endPoint, keyId, keySecret);
//组装文件地址
String host = "https://" + bucketName + "." + endPoint.split("//")[1] + "/";
//获取文件名称
String objectName = url.substring(host.length());
//删除文件
ossClient.deleteObject(bucketName, objectName);
} catch (Exception e) {
e.printStackTrace();
}
}
}
@RestController
@RequestMapping("/api/oss/file")
public class OSSController {
@Resource
private FileService fileService;
/**
* 文件上传
*
* @param file
* @param module
* @return
*/
@PostMapping("/upload")
public Result upload(MultipartFile file, String module) {
//返回上传到oss的路径
String url = fileService.upload(file, module);
return Result.ok(url).message("文件上传成功");
}
}
网友评论