文章目录
- 前言
- 一、初步阶段
- 1.1、认识OSS服务与开通OSS服务(创建Bucket、配置用户权限以及允许跨域)
- 1.2、起步demo:GetStartedSample(上传、删除案例)
- 二、实战系列
- 2.1、上传文件-简单上传
- 2.2、集成OSS的SDK包及封装阿里云OSS存储服务(上传、删除功能,含源码)
- 2.3、集成SpringCloud-Alibaba-OSS
- 环境依赖配置
- 2.3.1、实现普通上传
- 2.3.2、获取服务端签名(web端来实现上传功能)
- 注意点
- 参考资料
前言
学习文档:
- OSS Java SDK 3.13.2版本—阿里官方文档:可以看其中的起步案例
- 阿里云-OSS对象存储控制台:官方控制台
学习视频:
- Java项目《谷粒商城》Java架构师 | 微服务 | 大型电商项目:对应下面四节有详细开通OSS云服务的讲解以及上传文件普通示例+获取服务端签名通过web端上传
一、初步阶段
1.1、认识OSS服务与开通OSS服务(创建Bucket、配置用户权限以及允许跨域)
阿里云开通OSS存储服务可见我的博客:阿里云开通OSS存储服务详细流程
2022.11.11编辑最新流程文档:创建Bucket、配置用户权限以及允许跨域
若是我们仅仅用来自己项目测试的话可以按照下面的来进行创建:
记住要为对应的bucket设置对应的用户权限:对于创建子用户操作见我上面的文章链接跟着走一遍就行!
配置跨域请求:
1.2、起步demo:GetStartedSample(上传、删除案例)
首先来到官方文档:
依赖:
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>3.14.0</version>
</dependency>
代码:已调试其中的带中文注释
package com.changlu.test.common;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Writer;
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.*;
/**
* This sample demonstrates how to get started with basic requests to Aliyun OSS
* using the OSS SDK for Java.
*/
public class GetStartedSample {
private static String endpoint = "";
private static String accessKeyId = "";
private static String accessKeySecret = "";
// private static String bucketName = "pictured-bed";
private static String bucketName = "";
private static String key = "test/test2/";//若是目录,一定要设置/
//方便之后拼接
private static String shortEndpoint = "oss-cn-beijing.aliyuncs.com";
public static void main(String[] args) throws IOException {
/*
* Constructs a client instance with your account for accessing OSS
*/
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
System.out.println("Getting Started with OSS SDK for Java\n");
try {
// /*
// * Determine whether the bucket exists 查看桶是否存在
// */
// if (!ossClient.doesBucketExist(bucketName)) { //创建桶
// /*
// * Create a new OSS bucket
// */
// System.out.println("Creating bucket " + bucketName + "\n");
// ossClient.createBucket(bucketName);//根据当前的认证信息来进行创建Bucket桶,默认是私有
// CreateBucketRequest createBucketRequest= new CreateBucketRequest(bucketName);
// createBucketRequest.setCannedACL(CannedAccessControlList.PublicRead);//设置读写权限为公开读
// ossClient.createBucket(createBucketRequest);//来
// }
/*
* List the buckets in your account:获取所有的桶名称
*/
// System.out.println("Listing buckets");
//
// ListBucketsRequest listBucketsRequest = new ListBucketsRequest();
// listBucketsRequest.setMaxKeys(500);
//
// for (Bucket bucket : ossClient.listBuckets()) { //发起请求
// System.out.println(" - " + bucket.getName());
// }
// System.out.println();
//
/*
* 上传文件
* Upload an object to your bucket:上传对象到你的桶中
*/
// System.out.println("Uploading a new object to OSS from a file\n");
// File file = new File("C:\\Users\\93997\\Desktop\\桌面壁纸\\1.png");
// String saveFilePath = key + file.getName();//拼接目标路径 + 图片名称
// //第一个参数为:桶的名称;第二个参数为路径+上你的文件名,如test/1.png,若是test/test2/1.png,也会给我们自动创建目录
// //第三个参数为:文件对象
// ossClient.putObject(new PutObjectRequest(bucketName,saveFilePath , file));
// //拼接获取公共访问地址
// String publicVisitPath = "http://" + bucketName + '.' + shortEndpoint + "/" + saveFilePath;
// System.out.println("访问路径:" + publicVisitPath);
//
// /*
// * 删除文件
// * Delete an object:删除对象
// */
System.out.println("Deleting an object\n");
File file = new File("C:\\Users\\93997\\Desktop\\桌面壁纸\\1.png");
String saveFilePath = key + file.getName();//拼接目标路径 + 图片名称
ossClient.deleteObject(bucketName, saveFilePath);
// /*
// * Determine whether an object residents in your bucket:判断对象是否存在你的桶
// */
// boolean exists = ossClient.doesObjectExist(bucketName, key);
// System.out.println("Does object " + bucketName + " exist? " + exists + "\n");
//
// ossClient.setObjectAcl(bucketName, key, CannedAccessControlList.PublicRead);
// ossClient.setObjectAcl(bucketName, key, CannedAccessControlList.Default);
//
// ObjectAcl objectAcl = ossClient.getObjectAcl(bucketName, key);
// System.out.println("ACL:" + objectAcl.getPermission().toString());
//
// /*
// * Download an object from your bucket
// */
// System.out.println("Downloading an object");
// OSSObject object = ossClient.getObject(bucketName, key);
// System.out.println("Content-Type: " + object.getObjectMetadata().getContentType());
// displayTextInputStream(object.getObjectContent());
//
// /*
// * List objects in your bucket by prefix
// */
// System.out.println("Listing objects");
// ObjectListing objectListing = ossClient.listObjects(bucketName, "My");
// for (OSSObjectSummary objectSummary : objectListing.getObjectSummaries()) {
// System.out.println(" - " + objectSummary.getKey() + " " +
// "(size = " + objectSummary.getSize() + ")");
// }
// System.out.println();
//
} 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 {
/*
* Do not forget to shut down the client finally to release all allocated resources.
*/
ossClient.shutdown();
}
}
private static File createSampleFile() throws IOException {
File file = File.createTempFile("oss-java-sdk-", ".txt");
file.deleteOnExit();
Writer writer = new OutputStreamWriter(new FileOutputStream(file));
writer.write("abcdefghijklmnopqrstuvwxyz\n");
writer.write("0123456789011234567890\n");
writer.close();
return file;
}
private static void displayTextInputStream(InputStream input) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(input));
while (true) {
String line = reader.readLine();
if (line == null) break;
System.out.println(" " + line);
}
System.out.println();
reader.close();
}
}
二、实战系列
2.1、上传文件-简单上传
配套代码:AliyunOss-SDK—Gitee、AliyunOss-SDK—Github
文档可见官网有对应不同功能的代码示例:简单上传文档
测试其中的上传文件流:直接复制的上面文件流的示例代码,然后去修改一下配置信息即可
package com.changlu;
import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import java.io.FileInputStream;
import java.io.InputStream;
public class Demo {
public static void main(String[] args) throws Exception {
// Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
String endpoint = "";
// 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
String accessKeyId = "";
String accessKeySecret = "";
// 填写Bucket名称,例如examplebucket。
String bucketName = "";
// 填写Object完整路径,完整路径中不能包含Bucket名称,例如exampledir/exampleobject.txt。
String objectName = "2.png";
// 填写本地文件的完整路径,例如D:\\localpath\\examplefile.txt。
// 如果未指定本地路径,则默认从示例程序所属项目对应本地路径中上传文件流。
String filePath= "C:\\Users\\93997\\Desktop\\桌面壁纸\\1.png";
// 创建OSSClient实例。
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
try {
InputStream inputStream = new FileInputStream(filePath);
// 创建PutObject请求。
ossClient.putObject(bucketName, objectName, inputStream);
} 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();
}
}
}
}
若是你的配置没有问题,程序不会报任何代码错误!
接下来检查一下对应阿里云的bucket文件列表是否有对应的文件:
2.2、集成OSS的SDK包及封装阿里云OSS存储服务(上传、删除功能,含源码)
配套代码:AliyunOssService-Gitee 、AliyunOssService-Github
上传、删除方法已经封装到Utils中,controller只需要调用工具类的上传、删除即可!
application.yml:
# 图片文件上传
spring:
servlet:
multipart:
max-file-size: 100MB
max-request-size: 1000MB
# 阿里云OSS配置
aliyun:
oss:
endpoint: # 坐标地区示例:oss-cn-beijing.aliyuncs.com
accessKeyId: # 注册用户的keyID
accessKeySecret: # 注册用户的密钥
bucketName: # 桶名称 示例:pictured-st
key: # 存储根路径,例如:img/,以目录形式为结尾,之后图片会自动生成并添加到后缀
package com.changlu.config;
import lombok.Data;
import lombok.ToString;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* @ClassName AliyunOssConfig
* @Author ChangLu
* @Date 3/26/2022 4:22 PM
* @Description 阿里云OOS配置
*/
@Component
// 指定配置文件中自定义属性前缀
@ConfigurationProperties(prefix = "aliyun.oss")
@Data
@ToString
public class AliyunOssConfig {
private String endpoint;
private String accessKeyId;
private String accessKeySecret;
private String bucketName;
private String key;
}
package com.changlu.controller;
import com.changlu.domain.ResponseResult;
import com.changlu.utils.AliyunOssUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.util.HashMap;
import java.util.Map;
/**
* @ClassName UploadController
* @Author ChangLu
* @Date 3/26/2022 5:23 PM
* @Description Oss文件控制器
*/
@RestController
public class OssFileController {
@Autowired
private AliyunOssUtil aliOssUtil;
/**
* 上传图片
* @param file
* @return
*/
@PostMapping("/upload")
public ResponseResult uploadFile(@RequestParam("file")MultipartFile file){
try {
String visitUrl = aliOssUtil.uploadFile(file);
Map<String,String> result = new HashMap<>(1);
result.put("visitUrl", visitUrl);
return new ResponseResult(200,"上传成功!", result);
}catch (Exception e){
e.printStackTrace();
return new ResponseResult(500,"上传失败!");
}
}
/**
* 删除图片
* @param fileName 文件名称如:b8809d28-82ec-4b06-af5f-8d3d7a16107c.jpg
* @return
*/
@GetMapping("/deleFile/{fileName}")
public ResponseResult deleteFile(@PathVariable("fileName")String fileName){
try {
aliOssUtil.deleteFile(fileName);
return new ResponseResult(200,"删除成功!");
} catch (Exception e) {
e.printStackTrace();
return new ResponseResult(500,"删除失败!");
}
}
}
import com.fasterxml.jackson.annotation.JsonInclude;
/**
* @Author changlu
*/
@JsonInclude(JsonInclude.Include.NON_NULL)
public class ResponseResult<T> {
/**
* 状态码
*/
private Integer code;
/**
* 提示信息,如果有错误时,前端可以获取该字段进行提示
*/
private String msg;
/**
* 查询到的结果数据,
*/
private T data;
public ResponseResult(Integer code, String msg) {
this.code = code;
this.msg = msg;
}
public ResponseResult(Integer code, T data) {
this.code = code;
this.data = data;
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public ResponseResult(Integer code, String msg, T data) {
this.code = code;
this.msg = msg;
this.data = data;
}
}
package com.changlu.utils;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.ObjectMetadata;
import com.aliyun.oss.model.PutObjectRequest;
import com.changlu.config.AliyunOssConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.InputStream;
import java.util.UUID;
/**
* @ClassName AliyunOssUtil
* @Author ChangLu
* @Date 3/26/2022 4:51 PM
* @Description OSS对象存储工具类
*/
@Component
public class AliyunOssUtil {
@Autowired
private AliyunOssConfig aliyunOssConfig;
/**
* 创建一个OSS连接
* @return OssClient
*/
private OSS createOssClient(){
String endpoint = "http://" + aliyunOssConfig.getEndpoint();
String accessKeyId = aliyunOssConfig.getAccessKeyId();
String accessKeySecret = aliyunOssConfig.getAccessKeySecret();
return new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
}
/**
* 关闭连接
* @param ossClient
*/
private void close(OSS ossClient){
if (ossClient != null) {
ossClient.shutdown();
}
}
/**
* 上传文件
* @param file File类型
* @return
*/
public String uploadFile(File file){
String key = aliyunOssConfig.getKey();
String bucketName = aliyunOssConfig.getBucketName();
String endpoint = aliyunOssConfig.getEndpoint();
//1、取得保存文件路径saveFilePath:拼接目标路径 + 图片名称
String originFileName = file.getName();
String filePrefix = UUID.randomUUID().toString();
String saveFileName = filePrefix + originFileName.substring(file.getName().indexOf("."));
String saveFilePath = key + saveFileName;
OSS ossClient = null;
try {
ossClient = createOssClient();
//2、上传文件
//第一个参数为:桶的名称;第二个参数为路径+上你的文件名,如test/1.png,若是test/test2/1.png,也会给我们自动创建目录
//第三个参数为:文件对象
ossClient.putObject(new PutObjectRequest(bucketName,saveFilePath , file));
}catch (Exception e){
e.printStackTrace();
return null;
}finally {
this.close(ossClient);
}
//3、拼接获取公共访问地址
String publicVisitPath = "http://" + bucketName + '.' + endpoint + "/" + saveFilePath;
return publicVisitPath;
}
/**
* 上传文件
* @param file MultipartFile类型
* @return
*/
public String uploadFile(MultipartFile file)throws Exception{
String key = aliyunOssConfig.getKey();
String bucketName = aliyunOssConfig.getBucketName();
String endpoint = aliyunOssConfig.getEndpoint();
//1、取得保存文件路径saveFilePath:拼接目标路径 + 图片名称
String originFileName = file.getOriginalFilename();
String filePrefix = UUID.randomUUID().toString();
String saveFileName = filePrefix + originFileName.substring(originFileName.indexOf("."));
String saveFilePath = key + saveFileName;
OSS ossClient = null;
try {
ossClient = createOssClient();
//2、上传文件
//第一个参数为:桶的名称;第二个参数为路径+上你的文件名,如test/1.png,若是test/test2/1.png,也会给我们自动创建目录
//第三个参数为:文件对象
/**
* 阿里云OSS 默认图片上传ContentType是image/jpeg
* 图片链接后,图片是下载链接,而并非在线浏览链接
* 这里在上传的时候要解决ContentType的问题,将其改为image/jpg
*/
InputStream is = file.getInputStream();
ObjectMetadata meta = new ObjectMetadata();
meta.setContentType("image/jpg");
ossClient.putObject(new PutObjectRequest(bucketName,saveFilePath , is, meta));
}catch (Exception e){
throw new RuntimeException(e);
}finally {
this.close(ossClient);
}
//3、拼接获取公共访问地址
String publicVisitPath = "http://" + bucketName + '.' + endpoint + "/" + saveFilePath;
return publicVisitPath;
}
/**
* 删除文件
* @param fileName 待删除的文件名
* @return
*/
public void deleteFile(String fileName)throws Exception{
String key = aliyunOssConfig.getKey();
String bucketName = aliyunOssConfig.getBucketName();
//1、拼接待删除路径
String deleteFilePath = key + fileName;
OSS ossClient = null;
try {
ossClient = createOssClient();
//2、删除文件
ossClient.deleteObject(bucketName, deleteFilePath);
}catch (Exception e){
throw new RuntimeException(e);
}finally {
this.close(ossClient);
}
}
}
2.3、集成SpringCloud-Alibaba-OSS
环境依赖配置
pom.xml:三个版本依次为springboot2.1.8
、springcloud Greenwich.SR3
、SpringCloud Alibaba2.1.0.RELEASE
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.8.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Greenwich.SR3</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alicloud-oss</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.1.0.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
2.3.1、实现普通上传
配套代码:springcloud-alibaba-oss-Gitee 、springcloud-alibaba-oss-Github
server:
port: 8888
spring:
cloud:
alicloud:
access-key:
secret-key:
oss:
endpoint:
# 这是自定义的,需要自己来去读取
bucketname:
接着对应demo写在了test的示例中:下面黄色框的就是我们需要自己额外编写的,其他的上传操作和之前的普通上传基本一致
package com.changlu;
import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSException;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
/**
* @Description:
* @Author: changlu
* @Date: 5:44 PM
*/
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringCloudOSSApplicationTest {
@Autowired
private OSS ossClient;
@Value("${spring.cloud.alicloud.oss.bucketname}")
private String bucketName;
//普通上传文件服务
@Test
public void test() {
// 填写Object完整路径,完整路径中不能包含Bucket名称,例如exampledir/exampleobject.txt。
String objectName = "4.png";
// 填写本地文件的完整路径,例如D:\\localpath\\examplefile.txt。
// 如果未指定本地路径,则默认从示例程序所属项目对应本地路径中上传文件流。
String filePath= "C:\\Users\\93997\\Desktop\\桌面壁纸\\1.png";
try {
InputStream inputStream = new FileInputStream(filePath);
// 创建PutObject请求。
ossClient.putObject(bucketName, objectName, inputStream);
} 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());
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
if (ossClient != null) {
ossClient.shutdown();
}
}
}
}
运行一下,若是没有任何报错信息的话,那么此时说就说上传成功:
2.3.2、获取服务端签名(web端来实现上传功能)
后端代码
配套代码:springcloud-alibaba-oss-Gitee 、springcloud-alibaba-oss-Github
文档地址:最佳实践-web端上传数据至OSS-服务器端直传并设置上传回调
pom.xml
:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.8.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.changlu</groupId>
<artifactId>springcloud-alibaba-oss</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springcloud-alibaba-oss</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Greenwich.SR3</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alicloud-oss</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.1.0.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>
application.yml
:
server:
port: 8888
spring:
cloud:
alicloud:
access-key:
secret-key:
oss:
endpoint:
# 这是自定义的,需要自己来去读取
bucketname:
R.java
:统一封装响应类
package com.changlu.utils;
import java.util.HashMap;
import java.util.Map;
/**
* 返回数据
*
* @author chenshun
* @email sunlightcs@gmail.com
* @date 2016年10月27日 下午9:59:27
*/
public class R extends HashMap<String, Object> {
private static final long serialVersionUID = 1L;
public R() {
put("code", 0);
put("msg", "success");
}
public static R error() {
return error(500, "未知异常,请联系管理员");
}
public static R error(String msg) {
return error(500, msg);
}
public static R error(int code, String msg) {
R r = new R();
r.put("code", code);
r.put("msg", msg);
return r;
}
public static R ok(String msg) {
R r = new R();
r.put("msg", msg);
return r;
}
public static R ok(Map<String, Object> map) {
R r = new R();
r.putAll(map);
return r;
}
public static R ok() {
return new R();
}
public R put(String key, Object value) {
super.put(key, value);
return this;
}
}
OssController.java
:提供获取签名服务
package com.changlu.controller;
import com.aliyun.oss.OSS;
import com.aliyun.oss.common.utils.BinaryUtil;
import com.aliyun.oss.model.MatchMode;
import com.aliyun.oss.model.PolicyConditions;
import com.changlu.utils.R;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* @Description:
* @Author: changlu
* @Date: 7:03 PM
*/
@RestController
public class OssController {
@Autowired
private OSS ossClient;
@Value("${spring.cloud.alicloud.oss.bucketname}")
private String bucketName;
@Value("${spring.cloud.alicloud.access-key}")
private String accessId;
@Value("${spring.cloud.alicloud.oss.endpoint}")
private String endpoint;
@RequestMapping("/oss/policy")
public R policy() {
// 填写Host地址,格式为https://bucketname.endpoint。
String host = "https://" + bucketName + "." + endpoint;
String dirName = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
// 设置上传到OSS文件的前缀,可置空此项。置空后,文件将上传至Bucket的根目录下。
String dir = dirName + "/";
Map<String, String> respMap = null;
try {
long expireTime = 30;
long expireEndTime = System.currentTimeMillis() + expireTime * 1000;
Date expiration = new Date(expireEndTime);
PolicyConditions policyConds = new PolicyConditions();
policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, 1048576000);
policyConds.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, dir);
//生成签名
String postPolicy = ossClient.generatePostPolicy(expiration, policyConds);
byte[] binaryData = postPolicy.getBytes("utf-8");
String encodedPolicy = BinaryUtil.toBase64String(binaryData);
String postSignature = ossClient.calculatePostSignature(postPolicy);
respMap = new LinkedHashMap<String, String>();
respMap.put("accessid", accessId);
respMap.put("policy", encodedPolicy);
respMap.put("signature", postSignature);
respMap.put("dir", dir);
respMap.put("host", host);
respMap.put("expire", String.valueOf(expireEndTime / 1000));
} catch (Exception e) {
// Assert.fail(e.getMessage());
System.out.println(e.getMessage());
}
return R.ok().put("data", respMap);
}
}
测试下:成功获取
前端代码
这里组件源代码可以直接可以查看谷粒商城博客笔记:谷粒商城-基础篇(详细流程梳理+代码)
这里面包含了组件源代码以及实际引入项目并使用的前端案例。
注意点
1、每次使用完OSSClient后要进行关闭,ossClient.shutdown()。
OSSClient不关闭,导致大量FullGC
2、可不可以设置OSSClient为单例?
- new OSSClient只是初始化一堆对象,并未建立长连接,如果你endpoint和权限是固定的,定义成static变量都行,只有在有实际操作时,才会httpClient.execute(),我每次都new这个客户端,是因为包装sdk给业务用时,CredentialsProvider这个是动态的
- 建议在方法中创建OSSClient 而不是使用@Bean注入,不然容易出现Connection pool shut down。
参考资料
[1] 一小时学会使用springboot操作阿里云OSS实现文件上传,下载,删除(附源码)
[2] SpringBoot整合阿里云OSS