1.对象存储OSS(Object Storage Service)
对象存储可以简单理解为用来存储图片、音频、视频
等非结构化数据的数据池。相对于云服务器,具有读写速度快,利于分享的特点。提供对象存储服务的平台有七牛云,阿里云和亚马逊等。
阿里云对象存储OSS(Object Storage Service)是一款海量、安全、低成本、高可靠的云存储服务,提供99.9999999999%(12个9)的数据持久性,99.995%的数据可用性。多种存储类型供选择,全面优化存储成本。
2.OSS购买与配置
在阿里云官网进行购买,新用户貌似可以白嫖三个月
购买完成之后还需要在控制台左侧找到对象存储OSS,并开通服务。
开通之后在OSS下创建Bucket
可以使用访问控制 RAM创建对应的子用户,并在之后使用其提供的accessKeyId 和accessKeySecret
生成子用户之后的accessKeySecret只会显示一次,记得提前保存好。
3.后端代码
OssUtils:
将传入的MultipartFile file对应的Byte数组上传到目标存储空间bucket中charsBlog/目录下。
MultipartFile一种可以接收使用多种请求方式来进行上传文件的代表形式。(如果使用spring框架来实现项目中的文件上传功能,则MultipartFile是最合适的选择。
上传成功之后访问图片的路径是:OSS管理控制台中对应bucket的外网访问域名 + /bucket下的文件夹 + 文件全名
package com.charsnows.blogapi.utils;
import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import java.io.ByteArrayInputStream;
/**
* @author Chars
*/
@Component
public class OssUtils {
public final String url = "http:// + 外网访问的Bucket域名 + /charsBlog/";
// Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
@Value("${oss.endpoint}")
private String endpoint;
// 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
@Value("${oss.accessKeyId}")
private String accessKeyId;
@Value("${oss.accessKeySecret}")
private String accessKeySecret;
// 填写Bucket名称,例如examplebucket。
@Value("${oss.bucketName}")
private String bucketName;
public boolean upload(MultipartFile file, String fileName) throws Exception {
// 填写Object完整路径,完整路径中不能包含Bucket名称,例如exampledir/exampleobject.txt。
String objectName = "charsBlog/" + fileName;
// 创建OSSClient实例。
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
try {
// 填写Byte数组。
byte[] content = file.getBytes();
// 创建PutObject请求。
ossClient.putObject(bucketName, objectName, new ByteArrayInputStream(content));
return true;
} 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();
}
}
return false;
}
}
附:阿里云官方文档给出的源代码:
上传Byte数组
以下代码用于将Byte数组上传到目标存储空间examplebucket中exampledir目录下的exampleobject.txt文件。
import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import java.io.ByteArrayInputStream;
public class Demo {
public static void main(String[] args) throws Exception {
// Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
// 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
String accessKeyId = "yourAccessKeyId";
String accessKeySecret = "yourAccessKeySecret";
// 填写Bucket名称,例如examplebucket。
String bucketName = "examplebucket";
// 填写Object完整路径,完整路径中不能包含Bucket名称,例如exampledir/exampleobject.txt。
String objectName = "exampledir/exampleobject.txt";
// 创建OSSClient实例。
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
try {
// 填写Byte数组。
byte[] content = "Hello OSS".getBytes();
// 创建PutObject请求。
ossClient.putObject(bucketName, objectName, new ByteArrayInputStream(content));
} 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();
}
}
}
}
UploadController:
调用OssUtils完成上传。
package com.charsnows.blogapi.controller;
import com.charsnows.blogapi.utils.OssUtils;
import com.charsnows.blogapi.vo.Result;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import java.util.UUID;
@RestController
@RequestMapping("upload")
public class UploadController {
@Autowired
private OssUtils ossUtils;
@PostMapping
public Result upload(@RequestParam("image")MultipartFile file) throws Exception {
//原始文件名称
String originalFilename = file.getOriginalFilename();
//随机生成唯一的文件名称
String fileName = UUID.randomUUID().toString() + "." + StringUtils.substringAfterLast(originalFilename, ".");
//上传文件
boolean upload = ossUtils.upload(file, fileName);
if(upload){
return Result.success(ossUtils.url + fileName);
}
return Result.fail(20001, "上传失败");
}
}
4.总结
测试页面显示成功,并上传到了对应的bucket中。
测试途中比较坑的是不知道accessKeySecret只会生成一次,还在控制台又找了半天。最后是使用win + v查看粘贴板才找回来的(因为之前复制过)。如果找不到了只能重新创建一个AccessKey。