AWS S3(对象存储)基本操作

平台:linux
语言:node


本文档只是记录一些S3的基本操作(基于AWS Node SDK),整体使用上看还是比较轻松好用的,比较复杂的特性请参见官方文档:
Restful API:
https://docs.aws.amazon.com/AmazonS3/latest/API/Welcome.html
Node SDK文档:
https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html

1 AWS S3对象存储

Amazon Simple Storage Service (Amazon S3) 是一种面向 Internet 的存储服务。您可以通过 Amazon S3 随时在 Web 上的任何位置存储和检索的任意大小的数据。

1.1 基本概念

Amazon S3将数据作为对象存储在存储区中。一个对象由一个文件和可选的描述该文件的任何元数据组成。在S3里面实质上是没有目录和文件夹的概念,即目录概念实质只是对象的前缀,并不存在实体。

###1.1.1 存储桶(bucket)
我们的数据都是存储在AWS 的存储桶中,我们可以把桶理解为磁盘分区,不过它是由一个桶名(字符串)唯一标识,即你不能创建别人已经创建过的桶。

1.1.2 对象

(1)对象键 (或键名称) 在存储桶中唯一地标识对象。(Key)
(2)对象元数据是一组名称值对。您可以在上传对象元数据时对其进行设置。上传对象后,您将无法修改对象元数据。修改对象元数据的唯一方式是创建对象的副本并设置元数据。对象元数据又分为系统元数据和用户自定义元数据。
(3) 数据

1.1.3 对象标签(tag)

使用存储对象打标签对存储进行分类。每个标签都是一个键-值对。
您可以将标签添加到新对象 (当您上传新对象时),也可以将标签添加到现有对象。请注意以下几点:

  • 您最多可以将 10 个标签与对象关联。与对象关联的标签必须具有唯一的标签键。
  • 标签键的长度最大可以为 128 个 Unicode 字符,标签值的长度最大可以为 256 个 Unicode 字符。
  • 键和值区分大小写。

标签对于对象管理相当好用所以重点说明
利用标签,您现在获得了另一个维度。如果您希望 photo1 属于项目 x 类别,则可以相应地标记该对象。除了数据分类之外,标签还提供其他好处。例如:

  • 对象标签支持权限的精细访问控制。例如,您可以向一个 IAM 用户授予仅读取带有特定标签的对象的权限。
  • 对象标签支持精细的对象生命周期管理,在其中,除了在生命周期规则中指定键名称前缀之外,还可以指定基于标签的筛选条件。
  • 使用 Amazon S3 分析时,您可以配置筛选条件,以便按对象标签、键名称前缀或前缀和标签的组合对对象进行分组以进行分析。
  • 您还可以自定义 Amazon CloudWatch 指标以按特定标签筛选条件显示信息。以下各节提供了详细信息。

1.2 S3存储类型

Amazon S3 中的每个对象都有与之关联的存储类别
这里写图片描述
对于经常访问的存储类均为STANDARD,我们默认也是该存储类

创建对象时,要指定键名称(Key),它在存储桶中唯一地标识该对象。可以理解为存储文件相对于当前桶的路径。

2 使用

2.1 安装AWS SDK

新建立一个文件夹,并下载AWS SDK

npm install aws-sdk

2.2 编写基础配置文件

var AWS = require('aws-sdk');
AWS.config.loadFromPath('./config/models/aws_config.json');
//加载访问密匙 密匙在AWS后台用户管理中得到
var s3 = new AWS.S3({signatureVersion: 'v4', region:'ap-northeast-2'});
//初始化SDK S3操作对象
//关于AWS服务区可参见:https://blog.csdn.net/m0_37263637/article/details/79226121
let targetBucket = "xxxxxbucket";
let targetKey =  "test/files/da123cadfeadfe/helloworld.jpg";
letbitmap = fs.readFileSync('./helloworld.jpg');

3 基础功能

下面的代码均基于2.2中代码

3.1 桶操作

3.1.1 创建桶

一个账户最多可以创建100个存储桶

var bucketParams = {
    Bucket: "xxxxtestbucket", //待创建的桶名
    CreateBucketConfiguration: {
     LocationConstraint: "ap-northeast-2"//桶所在服务区
    }
   };
s3.createBucket(bucketParams, function(err, data) {
    if (err) console.log(err, err.stack); // an error occurred
    else     console.log(data);           // successful response
});

3.1.2 桶的生命周期

往往实际应用中存在这样一种需求,我们希望云对象存储能自动管理一些文件,比如定时过期删除一些文件,或者将存储类型转换成更便宜的类型。
AWS 存储桶提供了生命周期这个功能。生命周期是针对储存桶而言的。
一个生命周期配置最多可以有 1000 个规则。 元素唯一地标识规则。ID 长度最多为 255 个字符。

下面代码只是针对过期操作

var lifecycleparams = {
    Bucket: targetBucket, //要配置生命周期的桶名
    LifecycleConfiguration: {
     Rules: [//规则组
        {
            Expiration: {
                Days:10//过期时间
            }, 
            Filter: {
                Prefix: "test/files/da123cadfeadfe/",//筛选器 针对该路径下的对象有效 该接口也提供tag 作为标识, 如果Prefix为空 为所有参数均有效
		  /*              
		 Tag: {//以标签精确管理过期时间
                          Key: 'STRING_VALUE', /* required */
                          Value: 'STRING_VALUE' /* required */
                  }*/
            }, 
            ID: "TestOnly", 
            Status: "Enabled", 
        }
     ]
    }
};
s3.putBucketLifecycleConfiguration(lifecycleparams, function(err, data) {
    console.info(data);
    if (err) console.log(err, err.stack); // an error occurred
    else   console.log(data);           // successful response
});

关于Filter参数,支持3种 ,但三种只能存在一种

  • Prefix:路径前缀
  • Tag:对象标签
  • And: 混合条件,即前缀标签均支持

And的形式为:

And: {
            Prefix: 'STRING_VALUE',
            Tags: [
              {
                Key: 'STRING_VALUE', /* required */
                Value: 'STRING_VALUE' /* required */
              },
              /* more items */
            ]
        },

同样s3 提供getBucketLifecycleConfiguration查看桶生命周期配置,deleteBucketLifecycle API删除桶生命周期配置。

3.1.3 删除桶

var deleteBucketParams = {
    Bucket: targetBucket
};

s3.deleteBucket(deleteBucketParams, function(err, data) {
    if (err) console.log(err, err.stack); // an error occurred
    else     console.log(data);           // successful response
});

桶不为空 SDK会报错

3.2 对象操作

3.2.1 上传对象

let putParams = {
    Bucket: targetBucket, 
    Key: targetKey, 
    Body: bitmap
};
s3.putObject(putParams, function(err, data) {
    if (err){
        console.error("put object error");
    }
    console.info(data);
});

3.2.2 获取对象

let getParams = {
    Bucket: targetBucket, 
    Key: targetKey
};

s3.getObject(getParams, function(err, data) {
    if (err){
        console.error("put object error");
    }
    console.info(data);
});

以http形式获取对象内容,返回为:

{ AcceptRanges: 'bytes',
  Expiration: 'expiry-date="Sun, 24 Jun 2018 00:00:00 GMT", rule-id="TestOnly"',
  LastModified: 2018-06-13T06:35:41.000Z,
  ContentLength: 94156,
  ETag: '"ec79ec01697b7a7f9e423108089c7c6f"',
  ContentType: 'application/octet-stream',
  Metadata: {},
  TagCount: 2,
  Body: <Buffer ff d8 ff e1 9b 2c 45 78 69 66 00 00 49 49 2a 00 08 00 00 00 0b 00 0f 01 02 00 06 00 00 00 92 00 00 00 10 01 02 00 1a 00 00 00 98 00 00 00 12 01 03 00 ... > }
}

3.2.3 复制对象

var copyParams = {
    Bucket: "xxx", //复制目标桶
    CopySource: "/xxx/test/files", //待复制资源位置:  /原桶/原桶对象键形式组成
    Key: "xxx"//复制目标对象键
};

s3.copyObject(copyParams, function(err, data) {
    if (err){
        console.info(err);
        console.error("put object error");
    }
    console.info(data);
});

3.2.4 删除对象

var deleteparams = {
    Bucket: targetBucket, 
    Key: targetKey
   };
   s3.deleteObject(deleteparams, function(err, data) {
     if (err) console.log(err, err.stack); // an error occurred
     else     console.log(data);           // successful response
});

3.2.5 删除文件夹

在AWS S3 实质上是没有文件夹的概念,文件夹可以理解为仅是对象名的前缀,S3可操作实体只有桶 和对象。
所以删除文件夹有两个方法:

  1. 在桶上为文件夹添加生命周期,匹配文件夹前缀,到期后48小时内将会被删除
  2. 利用S3批量操作接口先遍历文件夹,在批量删除。下面是这种方法 sample code。批量接口一次操作只支持1000,要更高需要对接口二次封装。

使用到了两个S3接口:
listObjects
deleteObjects

sample Code

const s3 = new AWS.S3({ accessKeyId: '', secretAccessKey: '', region: 'cn-north-1' });

function deleteS3Folder(BucketName, prefix, callback) {
  const getObjecsParam = {
    Bucket: BucketName,
    Prefix: prefix,
  }
  s3.listObjects(getObjecsParam, (err, data) => {  
    if (err) {
      console.error(err);
    }
    console.info(data);
    if (data.Contents.length === 0) {
      return callback(null);
    }
    if (data.Contents.length > 1000) {
      return callback('ths sample code does`t support 1000');
    }
    let deleteOnceArray = [];
    data.Contents.forEach((item) => {
      deleteOnceArray.push({ Key: item.Key });
    });
    console.info(deleteOnceArray);
    const deleteObjectsParam = {
      Bucket: BucketName,
      Delete: {
        Objects: deleteOnceArray,
      },
    };
    s3.deleteObjects(deleteObjectsParam, (deleteerr, deleteres) => {
      if (deleteerr) {
        console.error(deleteerr);
      }
      console.info(deleteres);
    });
  });
}

deleteS3Folder('BucketName', 'folderName', () => {
	console.info("delete success");
})

3.3 标签(tag)

3.3.1 为对象添加标签

var tagParams = {
    Bucket: targetBucket, 
    Key: targetKey, 
    Tagging: {
     TagSet: [
        {
       Key: "user", 
       Value: "testuser"
      }, 
        {
       Key: "vip", 
       Value: "Value4"
      }
     ]
    }
   };
   s3.putObjectTagging(tagParams, function(err, data) {
     if (err) console.log(err, err.stack); // an error occurred
     else     console.log(data);           // successful response
   });

3.3.2 获取对象标签内容

{ 
TagSet:
   [ { Key: 'vip', Value: 'Value4' },
     { Key: 'user', Value: 'testuser' } ]
 }

3.3.3 删除标签
 var deletTagparams = {
    Bucket: targetBucket, 
    Key: targetKey, 
   };
   s3.deleteObjectTagging(deletTagparams, function(err, data) {
     if (err) console.log(err, err.stack); // an error occurred
     else     console.log(data);           // successful response
   });

##3.4 预签名分享存储对象
如果要将对象短时间分享出去我们可以使用预签名,

let getSignedparams = {Bucket: targetBucket, Key: targetKey, Expires:60*30};//30 min
s3.getSignedUrl('getObject', getSignedparams, function(err, url){
    console.info(url);
});

返回为一个URL ,可以直接用浏览器通过访问这个URL下载存储对象。
虽然也可以通过这个API获取到putObject 的URL 但V4版签名需要在http header添加很多参数校验,不建议直接使用restful API 的方式操作。

4 使用中遇到的问题:

4.1 关于签名版本不正确的报错

The authorization mechanism you have provided is not supported. Please use AWS4-HMAC-SHA256.
因为SDK默认 还使用的是V2版签名,所以需要手动配置V4签名
var s3 = new AWS.S3({signatureVersion: ‘v4’, });

4.2 关于使用S3服务区配置错误的报错

Error parsing the X-Amz-Credential parameter; the region ‘us-east-1’ is wrong; expecting ‘ap-northeast-2’
新建的桶在首尔 而不是在美国,所以我们也应该配置地区为首尔。
var s3 = new AWS.S3({signatureVersion: ‘v4’, region:‘ap-northeast-2’});

4.3 关于S3目录(文件夹)的问题

S3目录 在S3里面是一个意思的东西。实质上S3中并没有目录的概念,可以目录理解为对象的key属性,仅是一串字符串,是对象前缀而已。
在我们使用PutObject 上传 Key 为 image/09/25/haha.jpg 。
该文件在S3控制台 可以看到 在image/ 09 / 25 的文件夹下。 如果仅通过这种方式 我们listObjectsV2 是list不到目录对象的。
但这里有一个非常有迷惑性的行为:
S3 控制台创建文件夹行为 实质上是使用PutObject API KEY: image/09/25/ 无Body字段,创建内容为空Object。
所以这种情况下去listObjects 是会list 得到这个空的目录对象的。

相关推荐
©️2020 CSDN 皮肤主题: Age of Ai 设计师:meimeiellie 返回首页