阿里云oss上传图片功能如何实现呢?
5 个回答
问题比较宽泛,云吞铺子大体总结了一下关于OSS上传的两种情况:一种是上传图片到OSS,另一种则是自行开发结合SDK和API实现上传功能,无论是哪种都很简单:
上传图片到OSS:
在OSS控制台新建bucket,您可以随意上传您的文件(包括图片),也可以自定义创建目录。可以直接使用网页版的OSS,也可以下载阿里云的OSS客户端。
SDK和API实现上传功能:
结合SDK和API自行开发上传功能,官方都有文档,官方提供SDK场景包括Java、Python、PHP、GO、C、.NET、iOS、Android、Node.js、Ruby等开发环境,直接参考: 阿里云OSS官方技术文档,用户可以参考左侧的SDK和Api文档自行开发功能,官方都有教程。
首先,附上 阿里云对象存储OSS官方文档地址
以下为整理的常用上传方式,基本优势劣势有个简单说明,并附上对应文档地址(OSS的文档还是比较丰富的,就是目录比较乱下,看中方案了可以直接去文档里面抄代码);
分类 | 使用方式 | 简单说明优缺点 | 适用场景 |
---|---|---|---|
前端表单直传OSS服务器 | 1.1js客户端签名并直传 | 在客户端通过JavaScript代码完成签名,无需过多配置,即可实现直传,非常方便。但是客户端通过JavaScript把AccesssKeyID和AccessKeySecret写在代码里面有泄露的风险 | 只推荐在能完全信任的内网环境使用 |
前端表单直传OSS服务器 | 1.2 js获取服务端签名后直传 STS | Web端向服务端请求签名,然后直接上传,不会对服务端产生压力,而且安全可靠。但服务端无法实时了解用户上传了多少文件,上传了什么文件。 | 适用于前后端分离项目绝大部分场景;其中文件上传后的信息由前端在实际业务中提交到后端进行保存; |
前端表单直传OSS服务器 | 1.3js获取 服务端签名直传并设置上传回调 | 用户上传完文件后,不会直接得到返回结果,而是先通知应用服务器,再把结果转达给用户 | 大多数情况下,用户上传文件后,应用服务器需要知道用户上传了哪些文件以及文件名;如果上传了图片,还需要知道图片的大小等,此时可以使用上传回调方案。 |
移动应用直传服务器 | 2.1官方文档 | 移动端发送请求到服务端获取临时签名,然后直传文件到OSS | 适用于前后端分离项目绝大部分场景;其中文件上传后的信息由前端在实际业务中提交到后端进行保存; |
移动应用直传服务器 | 2.2 回调文档 | 移动应用直传的情况下加入回调服务端 | 大多数情况下,用户上传文件后,应用服务器需要知道用户上传了哪些文件以及文件名;如果上传了图片,还需要知道图片的大小等,此时可以使用上传回调方案。 |
ecs中转 | 3.1 post到自己的ecs服务器,再上传oss | 通过自己的服务来做一次中转,会消耗ecs资源,但是上传文件可本地保留备份 | 一些文件上传低频B端应用可以使用该方案 |
文档地址
1.1js客户端签名并直传
1.2js获取服务端签名后直传
1.3js获取服务端签名直传并设置上传回调
2.1官方文档
2.2回调文档
3.1post到自己的ecs服务器,再上传oss
推荐用法
无,各场景不同,适合的方式不一样;可以参考上面写到的适用场景,资料仅为参考,自己的判断力更重要,加油!
备注:前面提到的都是一些基本场景,如果涉及到CDN以及多地冗余的高端应用,可以自己再去去看看文档,在配置上会有相应差异
一. 需求背景
小白: 我想在项目中实现图片上传,不知道有没有好用的第三方文件上传技术呢?
辉哥:那多了去了,阿里、腾讯、百度、七牛云等都有文件上传技术,你从中随便挑一个,我这就给你安排。
小白:阿里也有文件上传?!!!要不就给我安排阿里的实现方案吧。
辉哥:小子,你眼光不错哦。我这正好就有阿里OSS的图片处理文档,你拿去学习吧。
二. OSS简介
1. 快速了解
OSS(Object Storage Service)对象存储服务是一种海量、安全、低成本、高可靠的云存储服务,可以提供99.9999999999%(12个9)的数据持久性,99.995%的数据可用性。有多种存储类型可供选择,全面优化存储成本,非常适合存储非结构化的数据,例如视频、图形、日志、文本文件以及各种App应用、多终端同步软件、网盘下载站的文件等。
2. 存储类型
OSS支持的具体存储类型较多,我们可以参考如下链接: https://oss.console.aliyun. com/overview
2.1 标准存储(Standard)
该方案提供高可靠、高可用、高性能的对象存储服务,能够支持频繁的数据访问,适用于各种社交、分享类的图片、音视频应用、大型网站、大数据分析等业务场景。OSS还提供了标准存储-本地冗余(LRS)和标准存储-同城冗余(ZRS)两种数据冗余存储方式。
- 标准存储-本地冗余(LRS):采用数据冗余存储机制,将每个对象的不同冗余存储在同一个可用区内多个设施的多个设备上,确保硬件失效时的数据持久性和可用性。
- 标准存储-同城冗余(ZRS):采用多可用区(AZ)机制,将用户的数据分散存放在同一地域(Region)的3个可用区。当某个可用区不可用时,仍然能够保障数据的正常访问。
2.2 低频访问(Infrequent Access)
该方案提供了高持久性、较低存储成本的对象存储服务,有最低存储时间(30天)和最小计量单位(64 KB)要求。支持数据实时访问,访问数据时会产生数据取回费用,适用于较低访问频率(平均每月访问频率1到2次)的业务场景。提供低频访问-本地冗余(LRS)和低频访问-同城冗余(ZRS)两种数据冗余存储方式。
- 低频访问-本地冗余(LRS):采用数据冗余存储机制,将每个对象的不同冗余存储在同一个可用区内多个设施的多个设备上,确保硬件失效时的数据持久性和可用性。
- 低频访问-同城冗余(ZRS):采用多可用区(AZ)机制,将用户的数据分散存放在同一地域(Region)的3个可用区。当某个可用区不可用时,仍然能够保障数据的正常访问。
2.3 归档存储(Archive)
该方案提供了高持久性、极低存储成本的对象存储服务。有最低存储时间(60天)和最小计量单位(64 KB)要求。数据需解冻(约1分钟)后访问,解冻会产生数据取回费用。适用于数据长期保存的业务场景,例如档案数据、医疗影像、科学资料、影视素材等。
2.4 冷归档存储(Cold Archive)
该方案提供了高持久性的对象存储服务,存储费用在四种存储类型中最低。有最低存储时间(180天)和最小计量单位(64 KB)要求。数据需解冻后访问,解冻时间根据数据大小和选择的解冻模式决定,解冻会产生数据取回费用。
适用于需要超长时间存放的极冷数据,例如因合规要求需要长期留存的数据、大数据及人工智能领域长期积累的原始数据、影视行业长期留存的媒体资源、在线教育行业的归档视频等业务场景。
给大家介绍了以上这些存储类型之后,接下来我就带各位看看OSS到底该如何使用,本案例采用标准存储进行实现。
三. 快速使用
1. 开通服务
在使用OSS之前,我们要先购买OSS服务,毕竟这些第三方公司都不是做慈善的,怎么可能让我们免费使用这些吊炸天的技术呢?我们就掏点money,为让马爸爸成为首富贡献自己的绵薄之力吧。
在学习阶段,我们购买OSS时,可以选择按量计费的方案,当然也可以直接买一个半年包或者一年包!这些在学习时进行测试就已经足够了。我们可以看到,40GB存储包也就9块钱,便宜啊,买买买!
阿里云购买地址也给大家准备好啦: https://common-buy.aliyun.com/spm=5176.7933691.1309819..68b22a66FQKm7f&commodityCode=ossbag&request
2. 创建存储空间
购买了OSS服务之后,接下来需要创建自己的存储空间,创建过程如下图所示:
3. 上传测试
接下来我们可以先通过手动方式测试一下上传功能是否好使。
四. 代码实现
当然,我们在开发时不可能采用手动上传的方式实现文件上传,肯定是要利用代码进行实现的,接下来就给大家说说用代码该怎么实现文件上传。
1. 添加依赖
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>3.10.2</version>
</dependency>
2. 创建AccessKey
OSS为了提高安全性,要求每个用户都必须创建AccessKey,作为访问令牌,所以请按下图所示创建获取自己的AccessKey。
AccessKey简称AK,指的是访问身份验证中用到的AccessKeyId和AccessKeySecret。
大家要保存好自己的AK,不要随意泄露给别人哦。
3. 定义3个常量值
我们可以随便定义一个接口类,在其中定义如下3个常量值,用于存储自己的AK等信息。
public static final String endpoint = “所选服务器的地址 ,可以上传一张图片看看”;
public static final String accessKeyId = "xxxxx";
public static final String accessKeySecret = "xxxxx";
4. 文件上传下载文档
对于文件上传下载的具体实现过程,我们可以参考如下官方文档。
https://help.aliyun.com/document_detail/84781.html
5. 上传功能
为了方便实现图片上传,我定义了一个上传图片的方法,该方法可以定义在工具类中。
/**
* @param objectName 有没有二级目录 如果有 目录1/目录2/文件名
* @param content byte[ 图片的字节数组
* @return
* @throws Exception
*/
public static String uploadImage(
String objectName,
byte[] content) throws Exception {
// 创建OSSClient实例。
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
// 创建上传文件的元信息,可以通过文件元信息设置HTTP header(设置了才能通过返回的链接直接访问)。
ObjectMetadata objectMetadata = new ObjectMetadata();
objectMetadata.setContentType("image/jpg");
// 文件上传
ossClient.putObject(bucketName, objectName, new ByteArrayInputStream(content), objectMetadata);
// 设置URL过期时间为1小时。
Date expiration = new Date(System.currentTimeMillis() + 60*60 * 1000);
//返回url地址
String url = ossClient.generatePresignedUrl(bucketName, objectName, expiration).toString();
//关闭OSSClient。
ossClient.shutdown();
return url;
}
6. 下载功能
为了方便实现图片下载,我又定义了一个下载图片的方法,该方法也可以定义在工具类中。
/**
* @param objectName
* @param localFile
* @throws Exception
*/
public static void downFile(
String objectName,
String localFile) throws Exception {
// 创建OSSClient实例。
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
// 下载OSS文件到本地文件。如果指定的本地文件存在会覆盖,不存在则新建。
ossClient.getObject(new GetObjectRequest(bucketName, objectName), new File(localFile));
// 关闭OSSClient。
ossClient.shutdown();
}
7. 删除功能
最后,我们再搞一个文件删除功能,代码如下:
/**
* @param objectName
*/
public static void deleteFile(
String objectName) {
// 创建OSSClient实例。
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
// 删除文件。如需删除文件夹,请将ObjectName设置为对应的文件夹名称。如果文件夹非空,则需要将文件夹下的所有object删除后才能删除该文件夹。
ossClient.deleteObject(bucketName, objectName);
// 关闭OSSClient。
ossClient.shutdown();
}
五. 结语
我们在开发中会接触到很多的第三方文件服务器,在学习时首先要下载对应的sdk,并查看官方文档,根据官方文档的要求一步步进行实现即可。其实越是第三方的技术,使用起来越简单,因为如果第三方的功能使用起来太复杂,就会减少大家的使用兴趣,从而阻碍了该产品的推广。
现在你知道阿里OSS怎么使用了吗?如果你还有什么问题,可以在评论区给我留言或私信哦。
最后分享一套JavaWeb视频,从零基础入门到项目实战,让你学习Java不迷茫!!!
想要更多海量Java学习资料包(教程+源码+学习笔记+工具+课件+面试题解析),可以后台回复:Java 即可免费领取!
引入相关依赖
<!-- https://mvnrepository.com/artifact/com.aliyun.oss/aliyun-sdk-oss -->
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>2.8.3</version>
</dependency>
<!-- https://mvnrepository.com/artifact/joda-time/joda-time -->
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>2.10.10</version>
</dependency>
上传实现
controller
/**
* 文件上传
*/
@PostMapping("upload")
public R upload(@RequestParam("file") MultipartFile file) {
String uploadUrl = fileService.upload(file);
return R.ok().put("url", uploadUrl);
}
service
public String upload(MultipartFile file) {
//阿里云存储相关常量
String endPoint = ;
String accessKeyId = ;
String accessKeySecret = ;
String bucketName = ;
String fileHost = ;
String uploadUrl = ;
try {
OSSClient ossClient = new OSSClient(endPoint, accessKeyId, accessKeySecret);
if (!ossClient.doesBucketExist(bucketName)) {
ossClient.createBucket(bucketName);
ossClient.setBucketAcl(bucketName, CannedAccessControlList.PublicRead);
}
InputStream inputStream = file.getInputStream();
String filePath = new DateTime().toString("yyyy/MM/dd");
String original = file.getOriginalFilename();
String fileName = UUID.randomUUID().toString();
String fileType = original.substring(original.lastIndexOf("."));
String newName = fileName + fileType;
String fileUrl = fileHost + "/" + filePath + "/" + newName;
ossClient.putObject(bucketName, fileUrl, inputStream);
ossClient.shutdown();
uploadUrl = "http://" + bucketName + "." + endPoint + "/" + fileUrl;
}catch (Exception e){
return null;
}
return uploadUrl;
}
# 上期回顾
kafka producer同异步发送信息
我们的任务是:先上传在线图片到oss,然后获取图片路径推送到kafka中,上期我们分享了推送数据到kafka,这一期我们分享将在线图片上传到oss中。
阿里云oss简单使用,可先看这一篇
java实现生产并消费rocketmq数据并将数据上传到存储服务器上06:阿里云oss上传数据
废话不多说,开干!!
引入maven包
<!-- OSS SDK 相关依赖 -->
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>3.8.0</version>
</dependency>
oss的配置
配置文件
# 0 阿里公有云oss 1 minio(目前未支持)
oss.type=1
oss.accessKeyId=xxxx
oss.accessKeySecret=xxxx
oss.endpoint=oss-cn-xx.xx.com
oss.bucketName=xx
#缩略图默认高
oss.zoom-high=200
#缩略图默认高
oss.zoom-wide=200
oss.upload-type=jpg
#地址过期时间
oss.day=30
配置类
/**
* @author :dzp
* @date :Created in 2021/8/23 16:43
* @description:
*/
@Configuration
@ConfigurationProperties(prefix = "oss")
@Setter
@Getter
public class OSSConfig {
private String accessKeyId;
private String accessKeySecret;
private String endpoint;
private String bucketName;
private int day=30;
private Integer type=0;
private int zoomHigh=200;
private int zoomWide=200;
private String uploadType="jpg";
}
创建一个操作oss的接口类
/**
* @author :dzp
* @date :Created in 2022/3/10 14:05
* @description:
*/
public interface OssClientService {
OSSPicture uploadOSS(String path, String cameraId, String ytfiletype, String style);
}
阿里云接口类继承上述接口
public interface ALiYunClientService extends OssClientService {
}
这里说下为什么这样设计的原因是 后期可能需要切换成亚马逊的sdk,可方便调整。
创建一个返回图片路径的类
/**
* @author :dzp
* @date :Created in 2022/3/10 11:05
* @description:
*/
@Setter
@Getter
public class OSSPicture {
// 获取原图
private String originalDrawing;
//缩略图
private String thumbnail;
public OSSPicture(String originalDrawing, String thumbnail) {
this.originalDrawing = originalDrawing;
this.thumbnail = thumbnail;
}
public OSSPicture(){
}
}
上传在线图片到oss
@Service
public class ALiYunClientServiceImpl implements ALiYunClientService {
@Resource
private OSSConfig ossConfig;
/**
*上传并获取路径
* @param path 路径
* @param cameraId id
* @return
*/
@Override
public OSSPicture uploadOSS(String path, String cameraId, String ytfiletype, String style) {
///data/年月日/carmerid/carmerid_timestamp.jpg
String updateType = StringUtils.hasLength(ytfiletype) ? ytfiletype : ossConfig.getUploadType();
String fileName = "data" +
"/" + DateUtils.getDays(new Date()) +
"/" +cameraId + "_" + System.currentTimeMillis() + "."+updateType ;
File file = null;
try {
//3 获取文件信息,为了上传
OSS ossClient = new OSSClientBuilder().build(ossConfig.getEndpoint(),
ossConfig.getAccessKeyId(),
ossConfig.getAccessKeySecret());
String bucketName = ossConfig.getBucketName();
boolean isExist = ossClient.doesBucketExist(bucketName);
if(!isExist) {
//bucketName 不存在 就创建。
ossClient.createBucket(bucketName);
}
file = FileUtils.getFile(path);
PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName,fileName, file);
// 如果需要上传时设置存储类型和访问权限,请参考以下示例代码。
ObjectMetadata metadata = new ObjectMetadata();
metadata.setHeader(OSSHeaders.OSS_STORAGE_CLASS, StorageClass.Standard.toString());
putObjectRequest.setMetadata(metadata);
putObjectRequest.setVersionId("2");
// 上传字符串。
ossClient.putObject(putObjectRequest);
//5 关闭ossClient
ossClient.shutdown();
//6 返回上传之后地址,拼接地址
return new OSSPicture();
}catch(Exception e) {
e.printStackTrace();
return null;
}finally {
//删除本地临时文件
if(file!=null) file.delete();
}
}
}
将在线图片转为file对象
public class FileUtils {
/**
* 将图片转为file
*
* @param url 图片url
* @return File
*/
public static File getFile(String url) {
//读取图片类型
String fileName = url.substring(url.lastIndexOf("."));
File file = null;
URL urlfile;
InputStream inStream = null;
OutputStream os = null;
try {
file = File.createTempFile("oss_tmp_file_", fileName);
//获取文件
urlfile = new URL(url);
inStream = urlfile.openStream();
os = new FileOutputStream(file);
int bytesRead = 0;
byte[] buffer = new byte[8192];
while ((bytesRead = inStream.read(buffer, 0, 8192)) != -1) {
os.write(buffer, 0, bytesRead);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (null != os) {
os.close();
}
if (null != inStream) {
inStream.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
return file;
}
}
这里额外说明一下 为什么需要将在线图片下载到本地然后再上传 主要有2个原因 1.可能oss和提供的图片地址网络不互通。
2.在线地址不能直接使用。如果直接在File对象中传入在线地址可能会出现以下异常。
所以我这面还是推荐先把在线图片先下载到本地 然后再上传到阿里云oss中
测试接口
@RestController
public class OSSTestController {
@Resource
private ALiYunClientService aLiYunClientService;
#修改成图片的在线地址
@RequestMapping("/upload/test")
public OSSPicture upload() throws Exception {
OSSPicture ossPicture = aLiYunClientService.uploadOSS("http://xx.xx.xx.xx:xx/getimg/xx/2/xx.png",
String.valueOf(System.currentTimeMillis()),
null, null);
return ossPicture;
}
}
验证已上传成功。
这里我使用的是oss-browser客户端,如果大家没有下载,可进行下载。
oss-browser-win32-x64.zip
java交流群(限订阅了的加):868794080