在还没有工作时,我们做项目时一般使用的Tomcat服务器作为文件上传和下载的存储点。可是作为上线项目这是行不通,所以为了解决海量数据存储与弹性扩容,阿里云给我们提供了一个OOS的对象存储平台。
前提:必须申请开通OOS服务
[1] 申请阿里云账号 (这里可以通过支付宝一键登录)
[2] 实名认证 (绑定支付宝后,实名十分简单)
[3] 开通“对象存储OOS” 服务
若是第一次进入是开通 (开通后则会显示管理控制台)
[4] 进入管理控制台
[5] 创建Bucket
[6] 创建完Bucket后可以自行上传文件
[7] 上传完文件可以进行详情查看
通过URL可以下载该图片
[8] 我们可以查看官方文档对该功能进行学习(即通过代码操作上述步骤)
[1] 新建一个拥有Web依赖的Boot项目
[2] 在pom.xml引入依赖
<dependencies>
<!--阿里云oss依赖(必须)-->
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>3.10.2</version>
</dependency>
<!--日期工具依赖(非必须)-->
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>2.10.1</version>
</dependency>
</dependencies>
[3] 编写一个配置文件 application.properties
这里可以通过官方文档直接创建一个实例(不过我们为了变量的复用,使用配置文件的形式)
#服务端口
server.port=8082
#服务名
spring.application.name=service-oss
#环境设置:dev、test、prod
spring.profiles.active=dev
#阿里云 OSS
#不同的服务器,地址不同
aliyun.oss.file.endpoint= 你服务器所在的地址
aliyun.oss.file.keyid=
aliyun.oss.file.keysecret=
#bucket可以在控制台创建,也可以使用java代码创建
aliyun.oss.file.bucketname=
上面关于服务器配置的值可在下面找到:
endpoint 地域节点
获取自己的 id和 密钥
bucketname的话可以自行设置创建的名字
[4] 若此时直接通过boot启动类开启,则会报错 (若整合了数据库忽略该点)
报错原因:
spring boot 会默认加载org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration这个类,
而DataSourceAutoConfiguration类使用了@Configuration注解向spring注入了dataSource bean,又因为项目中并没有关于dataSource相关的配置信息,所以当spring创建dataSource bean时因缺少相关的信息就会报错。
解决办法:
在@SpringBootApplication注解上加上exclude,解除自动加载DataSourceAutoConfiguration
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
[5] 编写一个读取配置文件的工具类
ConstantPropertiesUtils.class,该类实现InitializingBean 主要是为了让该类在spring托管下,启动时能注入配置文件的值。(作用:注入值)
package com.gs.oss.utils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
//当项目自己启动,spring接口,spring加载之后,执行接口的一个方法
@Component
public class ConstantPropertiesUtils implements InitializingBean {
//读取配置文件内容
@Value("${aliyun.oss.file.endpoint}")
private String endpoint;
@Value("${aliyun.oss.file.keyid}")
private String keyId;
@Value("${aliyun.oss.file.keysecret}")
private String keySecret;
@Value("${aliyun.oss.file.bucketname}")
private String bucketName;
public static String END_POINT;
public static String ACCESS_KEY_ID;
public static String ACCESS_KEY_SECRET;
public static String BUCKET_NAME;
@Override
public void afterPropertiesSet() throws Exception {
END_POINT = endpoint;
ACCESS_KEY_ID = keyId;
ACCESS_KEY_SECRET = keySecret;
BUCKET_NAME = bucketName;
}
}
上面的准备步骤是为了变量值的注入(若复用次数相对较少,你完全可以通过定义变量写入即可)
[5] 编写接口OssService
(若要上传文件一定要使用MultipartFile 类型)
package com.gs.oss.service;
import org.springframework.web.multipart.MultipartFile;
public interface OssService {
//上传头像到oss
public String uploadFileAvatar(MultipartFile file);
}
[6] 编写OssService的实现类
步骤:
<1>读取服务对象的值
<2> 创建OSSClient实例。
<3>获取上传文件的输入流
中间的步骤是为了设置文件名而已
<4> 调用OSSClient的putObject() 方法实现文件上传
<5>关闭OSSClient。
<6> 把上传之后文件路径返回(需要把上传到阿里云的oss路径手动拼接出来,因为每个路径都是有规律的)
例子: https://edu-test10.oss-cn-hangzhou.aliyuncs.com/微信图片_20200717211750.jpg
“https://”+bucketName+"."+endpoint+"/"+filename;
bucketName: 放文件的bucket名,endpoint: 地域节点 , filename: 文件名
package com.gs.oss.service.Impl;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.gs.oss.service.OssService;
import com.gs.oss.utils.ConstantPropertiesUtils;
import org.joda.time.DateTime;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.UUID;
@Service
public class OssServiceImpl implements OssService {
//上传头像到oss
@Override
public String uploadFileAvatar(MultipartFile file) {
// Endpoint以杭州为例,其它Region请按实际情况填写。
String endpoint = ConstantPropertiesUtils.END_POINT;
String accessKeyId = ConstantPropertiesUtils.ACCESS_KEY_ID;
String accessKeySecret = ConstantPropertiesUtils.ACCESS_KEY_SECRET;
String bucketName = ConstantPropertiesUtils.BUCKET_NAME;
try{
// 创建OSSClient实例。
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
// 获取上传文件的输入流
InputStream inputStream = file.getInputStream();
//获取文件名称
String filename = file.getOriginalFilename();
//1.在文件名称里添加随机的唯一的值
String uuid = UUID.randomUUID().toString().replaceAll("-", "");
filename = uuid +"-"+ filename;
//2. 获取当前日期(2020/07/19)
String datePath = new DateTime().toString("yyyy/MM/dd");
// 2020/07/19/ewwqwa01.jpg
filename = datePath+"/"+filename;
//调用oss方法实现上传
//第一个参数 Bucket名称
//第二个参数 上传oss文件路径和文件名称 /aa/bb/1.jpg
//第三个参数 上传文件输入流
ossClient.putObject(bucketName, filename, inputStream);
// 关闭OSSClient。
ossClient.shutdown();
//把上传之后文件路径返回(需要把上传到阿里云的oss路径手动拼接出来)
// https://edu-test10.oss-cn-hangzhou.aliyuncs.com/微信图片_20200717211750.jpg
String url = "https://"+bucketName+"."+endpoint+"/"+filename;
return url;
}catch (Exception e){
return null;
}
}
}
[7] 编写Controller层
其中R表示的是我自定义的数据类型(可以直接返回字符串即可)
package com.gs.oss.controller;
import com.gs.commonutils.R;
import com.gs.oss.service.OssService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
@RestController
@RequestMapping("/eduoss/fileoss")
@CrossOrigin //这里是为了跨域(可以省略)
public class OssController {
@Autowired
private OssService ossService;
//上传头像的方法
@PostMapping
public R uploadOssFile(MultipartFile file){
//获取上传的文件 MultipartFile
//返回上传到oss的路径
String url = ossService.uploadFileAvatar(file);
return R.ok().data("url",url);
}
}
[8] 测试
这里我们如果没有整合Swagger的话,我们可以通过编写一个相应的前端页面(使用表单提交的方式进行测试);这里为了偷懒我直接使用Swagger进行测试接口(相关Swagger的整合可参考:SpringBoot整合Swagger2)
启动项目,并输入:http://localhost:8082/swagger-ui.html
选择相应的图片上传后可看到:
我们可以到OOS的控制台上查看服务端的文件