说明:注册用户时,经常会用到上传头像。文件的上传/接收与一般文本数据不同。
先准备一个Demo页面
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>图片上传title>
head>
<body>
<form method="post" action="/upload" enctype="multipart/form-data">
用户名:<input name="username" type="text" />
头像:<input name="image" type="file"/>
提交:<input type="submit" value="提交">
form>
body>
html>
需要注意,上传文件,页面端需要满足以下三个条件:
a. 表单上传框必须使用file类型,且必须得有name属性
b. 表单的提交方式必须是post
c. 表单的enctype值必须是mutipart-form/data(多部件文件上传),不写默认值(enctype=“application/x-www-form-urlencoded”),表示都是字符串上传
UploadController类
/**
* 本地磁盘存储:将用户上场的图片放入本机磁盘上
* @throws IOException
*/
@PostMapping("/upload")
public String uploadDemo(String username, MultipartFile image) throws IOException {
// 用户名,作参照,无意义,去掉也行
System.out.println(username);
// 1.获取用户上场的文件名
String filename = image.getOriginalFilename();
// 优化:为了保证图片名称的唯一性 不会被多用户覆盖
filename = UUID.randomUUID() + filename.substring(filename.lastIndexOf("."));
System.out.println(filename);
// 2 输出到指定磁盘下
image.transferTo(new File("D:\\imgTest\\" + filename));
return "上传成功";
}
测试,上传图片
需要记住以下几点:
a. 后端需要使用使用MutiPartFile对象接收图片;
b. 对象的属性名必须和页面提交的name一样
c. 默认接收的内容有大小限制,也自定义接收范围
(application.properties文件中配置)
#配置单个文件最大上传大小
spring.servlet.multipart.max-file-size=10MB
#配置单个请求最大上传大小(一次请求可以上传多个文件)
spring.servlet.multipart.max-request-size=100MB
使用本地磁盘存储,存在以下缺点:
(1)不安全:磁盘如果损坏,所有的文件就会丢失
(2)容量有限:如果存储大量的图片,磁盘空间有限(磁盘不可能无限制扩容)
(3)无法直接访问:需要服务器开机才行
对此,我们可以选择自己搭建存储服务器,或者使用现成的云服务,比如阿里云的OSS(对象存储)。
以下介绍使用阿里云OSS接收客户端上传的文件
可在SKD示例中找到,https://help.aliyun.com/document_detail/32009.html?spm=a2c4g.32008.0.0.5d2e3a3aX3TNv5
在Java对象/文件–>上传文件–>简单上传–>上传文件流里(https://help.aliyun.com/document_detail/84781.html?spm=a2c4g.32011.0.i7)
在个人中心里点AcccessKey,进入后点创建AccessKey,创建完成后,会有“accessKeyId”、“accessKeySecret”,相当于访问Bucket的账号密码
可以看到,已经上传成功,图片中的url,在实际开发中作为用户头像字段的值存入数据库,以供前端使用
阿里云官网提供的Demo,代码比较粗糙,可以将其精简,成为一个工具类。所需的配置,像数据库那样抽取出来,放在配置文件中,使用@ConfigurationProperties()注解,将配置值注入到对应的变量里,使用起来十分方便。
/**
* 阿里云 OSS 工具类
*/
@Data
@Component
@ConfigurationProperties(prefix = "oss")
public class AliOSSUtils {
private String endpoint;
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() + originalFilename.substring(originalFilename.lastIndexOf("."));
// 增加文件结构,按年月日区分文件
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
String date = sdf.format(new Date());
fileName = "image"+ "/" + date + "/" + fileName;
//上传文件到 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();
// 把上传到oss的路径返回
System.out.println(url);
return url;
}
}