阿里云对象存储OSS

目录:
一、什么是对象存储OSS
二、基本概念
2.1、存储空间(Bucket)
2.2、对象/文件(Object)
2.3、Region(地域)
2.4、Endpoint(访问域名)
2.5、AccessKey(访问密钥)
2.6、强一致性
2.7、数据冗余机制
2.8、OSS 与文件系统的对比
三、应用场景
3.1、图片和音视频等应用的海量存储
3.2、网页或者移动应用的静态和动态资源分离
3.3、云端数据处理
四、实战演练
4.1、创建 Bucket
4.2、文件管理
4.3、SpringBoot整合OSS,实现上传,下载以及查看
4.3.1、前期准备
4.3.2、配置application-oss.properties
4.3.3、创建一个配置类
4.3.4、文件上传到OSS
4.3.5、从OSS下载到本地
4.3.6、查看OSS存在的文件

一、什么是对象存储OSS

阿里云对象存储OSS(Object Storage Service)是阿里云提供的海量、安全、低成本、高可靠的云存储服务。其数据设计持久性不低于99.9999999999%(12个9),服务可用性(或业务连续性)不低于99.995%。

OSS具有与平台无关的RESTful API接口,您可以在任何应用、任何时间、任何地点存储和访问任意类型的数据。

二、基本概念

2.1、存储空间(Bucket)

存储空间是用户用于存储对象(Object)的容器,所有的对象都必须隶属于某个存储空间。存储空间具有各种配置属性,包括地域、访问权限、存储类型等。用户可以根据实际需求,创建不同类型的存储空间来存储不同的数据。

  • 同一个存储空间的内部是扁平的,没有文件系统的目录等概念,所有的对象都直接隶属于其对应的存储空间。
  • 每个用户可以拥有多个存储空间。
  • 存储空间的名称在 OSS 范围内必须是全局唯一的,一旦创建之后无法修改名称。
  • 存储空间内部的对象数目没有限制。

存储空间的命名规范如下:

  • 只能包括小写字母、数字和短横线(-)。
  • 必须以小写字母或者数字开头和结尾。
  • 长度必须在 3–63 字节之间。

2.2、对象/文件(Object)

对象是 OSS 存储数据的基本单元,也被称为 OSS 的文件。对象由元信息(Object Meta),用户数据(Data)和文件名(Key)组成。对象由存储空间内部唯一的 Key 来标识。对象元信息是一组键值对,表示了对象的一些属性,比如最后修改时间、大小等信息,同时用户也可以在元信息中存储一些自定义的信息。

对象的生命周期是从上传成功到被删除为止。在整个生命周期内,只有通过追加上传的 Object 可以继续通过追加上传写入数据,其他上传方式上传的 Object 内容无法编辑,您可以通过重复上传同名的对象来覆盖之前的对象。

对象的命名规范如下:

  • 使用 UTF-8 编码。
  • 长度必须在 1–1023 字节之间。
  • 不能以正斜线(/)或者反斜线(\)开头。

2.3、Region(地域)

Region 表示 OSS 的数据中心所在物理位置。Region 是在创建 Bucket 的时候指定的,一旦指定之后就不允许更改。该 Bucket 下所有的 Object 都存储在对应的数据中心,目前不支持 Object 级别的 Region 设置。

2.4、Endpoint(访问域名)

Endpoint 表示 OSS 对外服务的访问域名。OSS 以 HTTP RESTful API 的形式对外提供服务,当访问不同的 Region 的时候,需要不同的域名。通过内网和外网访问同一个 Region 所需要的 Endpoint 也是不同的。

2.5、AccessKey(访问密钥)

AccessKey(简称 AK)指的是访问身份验证中用到的 AccessKeyId 和 AccessKeySecret。OSS 通过使用 AccessKeyId 和 AccessKeySecret 对称加密的方法来验证某个请求的发送者身份。AccessKeyId 用于标识用户;AccessKeySecret 是用户用于加密签名字符串和 OSS 用来验证签名字符串的密钥,必须保密。对于 OSS 来说,AccessKey 的来源有:

  • Bucket 的拥有者申请的 AccessKey。
  • 被 Bucket 的拥有者通过 RAM 授权给第三方请求者的 AccessKey。
  • 被 Bucket 的拥有者通过 STS 授权给第三方请求者的 AccessKey。

2.6、强一致性

Object 操作在 OSS 上具有原子性,操作要么成功要么失败,不会存在有中间状态的 Object。OSS 保证用户一旦上传完成之后读到的 Object 是完整的,OSS 不会返回给用户一个部分上传成功的 Object。

Object 操作在 OSS 上同样具有强一致性,用户一旦收到了一个上传(PUT)成功的响应,该上传的 Object 就已经立即可读,并且 Object 的冗余数据已经写成功。不存在一种上传的中间状态,即 read-after-write 却无法读取到数据。对于删除操作也是一样的,用户删除指定的 Object 成功之后,该 Object 立即变为不存在。

2.7、数据冗余机制

OSS 采用数据冗余存储机制,将每个对象的不同冗余存储在同一个区域内多个设施的多个设备上,确保硬件失效时的数据可靠性和可用性。

  • OSS Object 操作具有强一致性,用户一旦收到了上传/复制成功的响应,则该上传的 Object 就已经立即可读,且数据已经冗余写入到多个设备中。
  • OSS 会通过计算网络流量包的校验和,验证数据包在客户端和服务端之间传输中是否出错,保证数据完整传输。
  • OSS 的冗余存储机制,可支持两个存储设施并发损坏时,仍维持数据不丢失。
    a.当数据存入 OSS 后,OSS 会检测和修复丢失的冗余,确保数据可靠性和可用性。
    b. OSS 会周期性地通过校验等方式验证数据的完整性,及时发现因硬件失效等原因造成的数据损坏。当检测到数据有部分损坏或丢失时,OSS 会利用冗余的数据,进行重建并修复损坏数据。

2.8、OSS 与文件系统的对比

OSS 与文件系统的对比

三、应用场景

3.1、图片和音视频等应用的海量存储

OSS可用于图片、音视频、日志等海量文件的存储。各种终端设备、Web网站程序、移动应用可以直接向OSS写入或读取数据。OSS支持流式写入和文件写入两种方式。


图片和音视频等应用的海量存储

3.2、网页或者移动应用的静态和动态资源分离

利用海量互联网带宽,OSS可以实现海量数据的互联网并发下载。OSS提供原生的传输加速功能,支持上传加速、下载加速,提升跨国、跨洋数据上传、下载的体验。


网页或者移动应用的静态和动态资源分离

3.3、云端数据处理

上传文件到OSS后,可以配合媒体处理服务和图片处理服务进行云端的数据处理。


云端数据处理

四、实战演练

前提:开始使用"对象存储OSS"首先要进入到阿里云控制台,控制台地址:https://oss.console.aliyun.com/overview

4.1、创建 Bucket

进入控制台,选择对象存储。然后点击创建Bucket,如下图所示


创建Bucket

4.2、文件管理

进入刚才创建的Bucket中,进行文件在线管理,如图所示


文件管理

4.3、SpringBoot整合OSS,实现上传,下载以及查看

4.3.1、前期准备

 <dependency>
            <groupId>com.aliyun.oss</groupId>
            <artifactId>aliyun-sdk-oss</artifactId>
            <version>2.8.3</version>
 </dependency>

4.3.2、配置application-oss.properties

##########阿里云对象存储OSS###################
aliyun.endpoint=oss-cn-shanghai.aliyuncs.com
aliyun.accessKeyId=*******
aliyun.accessKeySecret=*******
aliyun.bucketName=phone-xby
aliyun.urlPrefix=http://phone-xby.oss-cn-shanghai.aliyuncs.com/ 

4.3.3、创建一个配置类

import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClient;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;

/**
 *
 * @author Xiby
 *
 */
@Configuration
@PropertySource(value = {"classpath:application-oss.properties"})
@ConfigurationProperties(prefix = "aliyun")
@Data
public class AliyunConfig {
    private String endpoint;
    private String accessKeyId;
    private String accessKeySecret;
    private String bucketName;
    private String urlPrefix;
    @Bean
    public OSS oSSClient() {
        return new OSSClient(endpoint, accessKeyId, accessKeySecret);
    }
}

4.3.4、文件上传到OSS

4.3.4.1、Controller类

@Controller
public class AiliyunOSSController {


    @Autowired
    private AiliyunOSSService ailiyunOSSlService;

    /**
     * @param uploadFile
     * @return
     * @desc 上传文件到OOS
     */

    @RequestMapping(value = {"/ailiyunOSS/uplodeFile"}, method = RequestMethod.POST)
    @ResponseBody
    public Message uplodeFile(@RequestParam("file") MultipartFile uploadFile) {
        return ailiyunOSSlService.upload( uploadFile );
    }
}

4.3.4.2、Service类

import cn.hutool.core.date.DateTime;
import com.aliyun.oss.OSS;
import com.aliyun.oss.model.ListObjectsRequest;
import com.aliyun.oss.model.OSSObject;
import com.aliyun.oss.model.OSSObjectSummary;
import com.aliyun.oss.model.ObjectListing;
import org.apache.commons.lang3.RandomUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.net.URLEncoder;
import java.util.List;

@Service
public class AiliyunOSSServiceImpl implements AiliyunOSSService {

    private static final Logger logger = LoggerFactory.getLogger( Thread
            .currentThread().getStackTrace()[1].getClassName() );

    @Autowired
    private OSS ossClient;

    @Autowired
    private AliyunConfig aliyunConfig;



    @Override
    public Message upload(MultipartFile uploadFile) {

        Message m = new Message();

        String fileName = uploadFile.getOriginalFilename();

        try {
            ossClient.putObject( aliyunConfig.getBucketName(), fileName, new
                    ByteArrayInputStream( uploadFile.getBytes() ) );
        } catch (Exception e) {
            e.printStackTrace();
            //上传失败
            m.setResult( "002" );
            m.setDetail( "文件上传失败" );
            return m;
        }
        m.setResult( "001" );
        m.setDetail( "文件上传成功" );
        logger.info( "OSS存储路径:{URL=" + this.aliyunConfig.getUrlPrefix() + fileName + "}" );
        return m;
    }
}

4.3.4.3.前端(Layui)

  <div class="layui-form-item" style="margin: 10px 0;">
          <label class="layui-form-label">所属阶段</label>
                 <div class="layui-input-block">
                        <button type="button" class="layui-btn" id="test1">
                                <i class="layui-icon">&#xe67c;</i>导入
                         </button>
               </div>
    </div>
   var uploadInst = upload.render({
        elem: '#test1' //绑定元素
        ,url: '/ailiyunOSS/uplodeFile' //上传接口
        ,exts:'jpg|png|gif|bmp|jpeg|txt|word|docx|mp4|pdf|doc|xlsx|xls|pptx|ppt|wmv' 
        ,size:0
        ,done:function () {
            initTable();
        }

    });

4.3.5、从OSS下载到本地

4.3.5.1、Controller类

   /**
     *
     * @author Xiby
     * 
     * @desc 根据文件名下载oss上的文件
     *
     * @Param fileNames
     */
    @RequestMapping(value = {"/ailiyunOSS/exportFile/{fileNames:.*}"}, method = RequestMethod.GET)

    @ResponseBody
    public void downloadFile(@PathVariable("fileNames") String fileNames,HttpServletResponse response){

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType( MediaType.APPLICATION_OCTET_STREAM );
        ailiyunOSSlService.downloadFile(fileNames,response);


    }

4.3.5.2、Servicel类

    @Override
    public void downloadFile(String fileNames, HttpServletResponse response) {

        try {

            OSSObject ossObject = ossClient.getObject( aliyunConfig.getBucketName(), fileNames );
            BufferedInputStream in = new BufferedInputStream( ossObject.getObjectContent() );
            BufferedOutputStream out = new BufferedOutputStream( response.getOutputStream() );
            response.setHeader( "Content-Disposition", "attachment;filename=" + URLEncoder.encode( fileNames, "utf-8" ) );

            byte[] car = new byte[1024];
            int L = 0;
            while ((L = in.read( car )) != -1) {
                out.write( car, 0, L );
            }
            if (out != null) {
                out.flush();
                out.close();
            }
            if (in != null) {
                in.close();
            }
            ossClient.shutdown();

        } catch (Exception e) {
            e.printStackTrace();
        }

    }


4.3.5.3、前端

 <a class="layui-btn layui-btn-xs export" lay-event="exportCsv">下载</a>
 var $form = $('<form method="GET"></form>');
            $form.attr('action', '/ailiyunOSS/exportFile/'+ encodeURI(fileNames));
            $form.appendTo($('body'));
            $form.submit();

4.3.6、查看OSS存在的文件

4.3.6.1、Controller类

 @RequestMapping("/ailiyunOSS/queryFile")
    @ResponseBody
    public GriddataPageinfo list()
            throws Exception {
        return this.ailiyunOSSlService.list();
    }

4.3.6.2、Service类

 @Override
    public GriddataPageinfo list() {
        final int maxKeys = 100;
        ObjectListing objectListing = ossClient.listObjects( new ListObjectsRequest( aliyunConfig.getBucketName() ).withMaxKeys( maxKeys ) );
        List<OSSObjectSummary> sums = objectListing.getObjectSummaries();
        return new GriddataPageinfo( sums.size(), sums );
    }

4.3.6.3、前端

   var initTable = function () {
        tObj = table.render({
            id:'testReload',
            elem: '#datagrid',
            height: 500,
            url: web_path + '/ailiyunOSS/queryFile',
            response: {
                countName: 'total',
                dataName: 'rows'
            },
            page: true,
            cols: [[
                {field: 'bucketName',width: 200, title: '文件管理'},
                {field: 'lastModified',width: 200, title: '上传时间'},
                {field: 'key',width: 800, title: '文件存储路径'},
                {field: 'size',width: 225, title: '文件大小(B)'},
                {field: 'tools',fixed: 'right', title: '操作',  align: 'center', toolbar: '#showBar',width:150}
            ]]
        });

    };

目前文章就介绍到这里了,想要查看了解更多更详细的对象存储OSS的操作,请查看官方文档
本文参考文献:https://help.aliyun.com/document_detail/31817.html?spm=a2c4g.11186623.6.543.1fa66820dbcDTj

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342