一、文件上传
1. 文件上传功能
文件上传,是指将本地图片、视频、音频等文件上传到服务器,供其他用户浏览或下载的过程。
1.1 客户端上传文件三要素
客户端要把文件上传到服务端,需要满足一下三要素,否则仅仅是提交文件名,而不会提交文件内容:
- 使用表单方式提交,且表单提交方式是POST
- 表单的enctype属性要设置为multipart/form-data
- 表单里要有文件选择框,且文件选择框必须有name属性:
<input type="file" name="表单参数名">
示例:demo.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>文件上传-示例</title>
</head>
<body>
<!--
1. 使用表单方式提交数据,且表单提交方式为post
2. 表单form标签的enctype属性要设置为multipart/form-data
-->
<form action="/file/upload" method="post" enctype="multipart/form-data">
<!-- 3. 表单里要有文件选择框,且必须有name属性 -->
<input type="file" name="avatar"><br>
<button>提交</button>
</form>
</body>
</html>
1.2 服务端接收文件
在Controller里接收文件数据:
-
需要使用
MultipartFile类型的参数,MultipartFile对象的常用方法:getOriginalFilename():获取原始文件名(客户端上传的文件名称)getSize():获取文件的大小,单位是byte字节getInputStream():获取字节输入流对象,用于获取文件数据transferTo(File dest):把文件数据存储到本地磁盘上
-
默认允许上传的文件大小为1M,可以通过修改配置文件来调整限制
修改允许上传的文件大小
修改配置文件application.properties
#设置:一次请求最大允许提交20MB。默认10MB
spring.servlet.multipart.max-request-size=20MB
#设置:一个文件最大允许10MB。默认1MB
spring.servlet.multipart.max-file-size=10MB
2. 本地存储文件
所谓本地存储文件,是客户端把文件上传到服务器之后,服务器把文件直接存储到自己的磁盘里。
好处:简单
缺点:
- 本地磁盘空间有限,不能存储太多文件;且不方便扩容
- 本地存储文件,没有备份,一旦磁盘出现问题,就会丢失文件
- 维护管理不方便
示例代码:
@Slf4j
@RestController
@RequestMapping("/file")
public class FileController {
@PostMapping("/upload")
public Result upload(String name, MultipartFile avatar) throws IOException {
log.info("name={}", name);
//重命名文件
// 1. 获取原始文件名。比如:100.jpg
String filename = avatar.getOriginalFilename();
// 2. 截取得到后缀名。比如:.jpg
String suffix = filename.substring(filename.lastIndexOf("."));
// 3. 重新生成新的文件名。比如:2ceea81e-2a4d-4709-8332-367ea4e34e23.jpg
filename = UUID.randomUUID().toString() + suffix;
//保存文件到本地磁盘
avatar.transferTo(Paths.get("E:\" + filename));
log.info("文件已保存到:E:/{}", filename);
return Result.success();
}
}
3. 阿里云OSS存储
3.1 介绍
阿里云对象存储 OSS(Object Storage Service)是一款海量、安全、低成本、高可靠的云存储服务,提供最高可达 99.995 % 的服务可用性。多种存储类型供选择,全面优化存储成本。
3.2 阿里云OSS使用示例
阿里云OSS文档:help.aliyun.com/zh/oss/deve…
阿里云SDK介绍:help.aliyun.com/zh/oss/deve…
上传文件示例代码:help.aliyun.com/zh/oss/deve…
添加依赖
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>3.15.1</version>
</dependency>
上传示例
public class AliyunOSSTest {
public static void main(String[] args) throws Exception {
// Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
String endpoint = "https://oss-cn-beijing.aliyuncs.com";
// 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
DefaultCredentialProvider credentialProvider = new DefaultCredentialProvider("你的accessKeyId", "你的accessKeySecret");
// 填写Bucket名称,例如examplebucket。
String bucketName = "你的bucket名称";
// 填写Object完整路径,完整路径中不能包含Bucket名称,例如exampledir/exampleobject.txt。
String objectName = "aa/mm.jpg";
// 填写本地文件的完整路径,例如D:\localpath\examplefile.txt。
// 如果未指定本地路径,则默认从示例程序所属项目对应本地路径中上传文件流。
String filePath= "C:\Users\sdf\Desktop\img\32.jpg";
// 创建OSSClient实例。
OSS ossClient = new OSSClientBuilder().build(endpoint, credentialProvider);
try {
InputStream inputStream = new FileInputStream(filePath);
// 创建PutObjectRequest对象。
PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, inputStream);
// 创建PutObject请求。
PutObjectResult result = ossClient.putObject(putObjectRequest);
System.out.println(result);
} 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();
}
}
}
}
4. 上传员工头像
分析
实现
阿里云OSS工具类
@Component
public class AliOSSUtils {
private String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
private String accessKeyId = "*************";
private String accessKeySecret = "**************";
private String bucketName = "*****";
/**
* 实现上传图片到OSS
*/
public String upload(MultipartFile file) throws IOException {
// 获取上传的文件的输入流
InputStream inputStream = file.getInputStream();
// 避免文件覆盖
String originalFilename = file.getOriginalFilename();
String fileName = UUID.randomUUID().toString() + 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的路径返回
}
}
- 在类上添加
@Component - 修改配置参数endpoind、accessKeyId、accessKeySecret、bucket名称等,改成自己的
如果要上传文件时:
- 只要使用
@Autowired注入AliOSSUtils对象,调用它的upload方法就可以了
UploadController
@Slf4j
@RestController
public class UploadController {
@Autowired
private AliOSSUtils ossUtils;
@PostMapping("/upload")
public Result upload(MultipartFile image) throws IOException {
String url = ossUtils.upload(image);
return Result.success(url);
}
}