# S3 API

## S3 API 参考

本文档提供了 Alluxio S3 API 的详细参考，允许您使用流行的 Amazon S3 协议与 Alluxio 进行交互。提供的示例同时使用了 AWS CLI 和标准 REST 客户端（如 `curl`）。

### 存储桶操作

#### CreateBucket

在 Alluxio 中创建一个新的存储桶。

**方法：** `PUT`

**路径：** `/{bucket}`

**响应：**

* `200 - OK`：存储桶创建成功。

**示例：**

<details>

<summary>AWS CLI</summary>

```console
$ aws --profile alluxio-s3 --endpoint "http://localhost:29998/" s3api create-bucket \
  --bucket=testbucket

$ aws --profile alluxio-s3 --endpoint "http://localhost:29998/" s3api list-buckets
{
    "Buckets": [
        {
            "Name": "testbucket",
            "CreationDate": "2022-05-03T11:32:34.156000+00:00"
        }
    ]
}
```

</details>

<details>

<summary>REST 客户端</summary>

```console
$ curl -i -H "Authorization: AWS4-HMAC-SHA256 Credential=testuser/..." \
  -X PUT http://localhost:29998/testbucket

HTTP/1.1 200 OK
Date: Tue, 03 May 2022 21:35:05 GMT
Content-Length: 0
Server: Jetty(9.4.43.v20210629)

$ curl -i -H "Authorization: AWS4-HMAC-SHA256 Credential=testuser/..." \
  -X GET http://localhost:29998/
HTTP/1.1 200 OK
Date: Tue, 03 May 2022 21:35:23 GMT
Content-Type: application/xml
Content-Length: 161
Server: Jetty(9.4.43.v20210629)

<ListAllMyBucketsResult>
  <Buckets>
    <Bucket>
      <Name>testbucket</Name>
      <CreationDate>2022-05-03T14:34:56.420Z</CreationDate>
    </Bucket>
  </Buckets>
</ListAllMyBucketsResult>
```

</details>

***

#### DeleteBucket

删除一个现有的存储桶。存储桶必须为空才能被删除。

**方法：** `DELETE`

**路径：** `/{bucket}`

**响应：**

* `204 - No Content`：存储桶删除成功。

**示例：**

<details>

<summary>AWS CLI</summary>

```console
$ aws --profile alluxio-s3 --endpoint "http://localhost:29998/" s3api list-buckets
{
    "Buckets": [
        {
            "Name": "tempbucket",
            "CreationDate": "2022-05-03T11:55:58.134000+00:00"
        },
        {
            "Name": "testbucket",
            "CreationDate": "2022-05-03T11:32:34.156000+00:00"
        }
    ]
}

$ aws --profile alluxio-s3 --endpoint "http://localhost:29998/" s3api delete-bucket \
  --bucket=tempbucket

$ aws --profile alluxio-s3 --endpoint "http://localhost:29998/" s3api list-buckets
{
    "Buckets": [
        {
            "Name": "testbucket",
            "CreationDate": "2022-05-03T11:32:34.156000+00:00"
        }
    ]
}
```

</details>

<details>

<summary>REST 客户端</summary>

```console
$ curl -i -H "Authorization: AWS4-HMAC-SHA256 Credential=testuser/..." \
  -X GET http://localhost:29998/
HTTP/1.1 200 OK
Date: Tue, 03 May 2022 21:43:20 GMT
Content-Type: application/xml
Content-Length: 254
Server: Jetty(9.4.43.v20210629)

<ListAllMyBucketsResult>
  <Buckets>
    <Bucket>
      <Name>tempbucket</Name>
      <CreationDate>2022-05-03T14:43:03.651Z</CreationDate>
    </Bucket>
    <Bucket>
      <Name>testbucket</Name>
      <CreationDate>2022-05-03T14:34:56.420Z</CreationDate>
    </Bucket>
  </Buckets>
</ListAllMyBucketsResult>

$ curl -i -H "Authorization: AWS4-HMAC-SHA256 Credential=testuser/..." \
  -X DELETE http://localhost:29998/tempbucket
HTTP/1.1 204 No Content
Date: Tue, 03 May 2022 21:43:25 GMT
Server: Jetty(9.4.43.v20210629)

$ curl -i -H "Authorization: AWS4-HMAC-SHA256 Credential=testuser/..." \
  -X GET http://localhost:29998/
HTTP/1.1 200 OK
Date: Tue, 03 May 2022 21:43:28 GMT
Content-Type: application/xml
Content-Length: 161
Server: Jetty(9.4.43.v20210629)

<ListAllMyBucketsResult>
  <Buckets>
    <Bucket>
      <Name>testbucket</Name>
      <CreationDate>2022-05-03T14:34:56.420Z</CreationDate>
    </Bucket>
  </Buckets>
</ListAllMyBucketsResult>
```

</details>

***

#### ListBuckets

列出请求发送者拥有的所有存储桶。

**方法：** `GET`

**路径：** `/`

**响应：**

* `200 - OK`：返回一个包含存储桶列表的 XML 文档。

**示例：**

<details>

<summary>AWS CLI</summary>

```console
$ aws --profile alluxio-s3 --endpoint "http://localhost:29998/" s3api list-buckets
{
    "Buckets": [
        {
            "Name": "testbucket",
            "CreationDate": "2022-05-03T11:32:34.156000+00:00"
        }
    ]
}
```

</details>

<details>

<summary>REST 客户端</summary>

```console
$ curl -i -H "Authorization: AWS4-HMAC-SHA256 Credential=testuser/..." \
  -X GET http://localhost:29998/
HTTP/1.1 200 OK
Date: Tue, 03 May 2022 21:35:23 GMT
Content-Type: application/xml
Content-Length: 161
Server: Jetty(9.4.43.v20210629)

<ListAllMyBucketsResult>
  <Buckets>
    <Bucket>
      <Name>testbucket</Name>
      <CreationDate>2022-05-03T14:34:56.420Z</CreationDate>
    </Bucket>
  </Buckets>
</ListAllMyBucketsResult>
```

</details>

***

#### HeadBucket

此操作用于确定存储桶是否存在以及您是否有权访问它。

**方法：** `HEAD`

**路径：** `/{bucket}`

**响应：**

* `200 - OK`：存储桶存在且您有权访问。
* `404 - Not Found`：存储桶不存在。

**示例：**

<details>

<summary>AWS CLI</summary>

```console
$ aws --profile alluxio-s3 --endpoint "http://localhost:29998/" s3api head-bucket \
  --bucket=testbucket
```

</details>

<details>

<summary>REST 客户端</summary>

```console
$ curl -i -H "Authorization: AWS4-HMAC-SHA256 Credential=testuser/..." \
  --head http://localhost:29998/testbucket
HTTP/1.1 200 OK
Date: Tue, 15 Nov 2022 04:49:12 GMT
Content-Type: application/xml
Content-Length: 0
Server: Jetty(9.4.43.v20210629)
```

</details>

***

#### GetBucketTagging

检索与存储桶关联的标签。

**方法：** `GET`

**路径：** `/{bucket}?tagging`

**响应：**

* `200 - OK`：返回一个带有标签集的 XML 文档。

**示例：**

<details>

<summary>AWS CLI</summary>

```console
$ aws --profile alluxio-s3 --endpoint "http://localhost:29998/" s3api get-bucket-tagging \
  --bucket=testbucket
{
    "TagSet": [
        {
            "Key": "key1",
            "Value": "val1"
        },
        {
            "Key": "key2",
            "Value": "val2"
        }
    ]
}
```

</details>

<details>

<summary>REST 客户端</summary>

```console
$ curl -i -H "Authorization: AWS4-HMAC-SHA256 Credential=testuser/..." \
  -X GET "http://localhost:29998/testbucket?tagging"
HTTP/1.1 200 OK
Date: Tue, 03 May 2022 23:31:07 GMT
Content-Type: application/xml
Content-Length: 124
Server: Jetty(9.4.43.v20210629)

<Tagging>
  <TagSet>
    <Tag>
      <Key>key1</Key>
      <Value>val1</Value>
    </Tag>
    <Tag>
      <Key>key2</Key>
      <Value>val2</Value>
    </Tag>
  </TagSet>
</Tagging>
```

</details>

***

#### PutBucketTagging

向现有存储桶添加一组标签。

**方法：** `PUT`

**路径：** `/{bucket}?tagging`

**请求体：** 包含标签集的 XML 文档。

**响应：**

* `200 - OK`：标签添加成功。

**示例：**

<details>

<summary>AWS CLI</summary>

```console
$ aws --profile alluxio-s3 --endpoint "http://localhost:29998/" s3api get-bucket-tagging \
  --bucket=testbucket
{
    "TagSet": []
}

$ aws --profile alluxio-s3 --endpoint "http://localhost:29998/" s3api put-bucket-tagging \
  --bucket=testbucket --tagging='TagSet=[{Key=key1,Value=val1},{Key=key2,Value=val2}]'

$ aws --profile alluxio-s3 --endpoint "http://localhost:29998/" s3api get-bucket-tagging \
  --bucket=testbucket
{
    "TagSet": [
        {
            "Key": "key1",
            "Value": "val1"
        },
        {
            "Key": "key2",
            "Value": "val2"
        }
    ]
}
```

</details>

<details>

<summary>REST 客户端</summary>

```console
$ curl -i -H "Authorization: AWS4-HMAC-SHA256 Credential=testuser/..." \
  -X GET "http://localhost:29998/testbucket?tagging"
HTTP/1.1 200 OK
Date: Tue, 03 May 2022 23:30:25 GMT
Content-Type: application/xml
Content-Length: 28
Server: Jetty(9.4.43.v20210629)

<Tagging><TagSet/></Tagging>

$ cat tags.xml
<Tagging>
  <TagSet>
    <Tag>
      <Key>key1</Key>
      <Value>val1</Value>
    </Tag>
    <Tag>
      <Key>key2</Key>
      <Value>val2</Value>
    </Tag>
  </TagSet>
</Tagging>

$ curl -i -H "Authorization: AWS4-HMAC-SHA256 Credential=testuser/..." \
  -H "Content-Type: application/xml" \
  -X PUT "http://localhost:29998/testbucket?tagging" --data-binary "@tags.xml"
HTTP/1.1 200 OK
Date: Tue, 03 May 2022 23:31:05 GMT
Content-Length: 0
Server: Jetty(9.4.43.v20210629)

$ curl -i -H "Authorization: AWS4-HMAC-SHA256 Credential=testuser/..." \
  -X GET "http://localhost:29998/testbucket?tagging"
HTTP/1.1 200 OK
Date: Tue, 03 May 2022 23:31:07 GMT
Content-Type: application/xml
Content-Length: 124
Server: Jetty(9.4.43.v20210629)

<Tagging>
  <TagSet>
    <Tag>
      <Key>key1</Key>
      <Value>val1</Value>
    </Tag>
    <Tag>
      <Key>key2</Key>
      <Value>val2</Value>
    </Tag>
  </TagSet>
</Tagging>
```

</details>

***

#### DeleteBucketTagging

从存储桶中删除标签。

**方法：** `DELETE`

**路径：** `/{bucket}?tagging`

**响应：**

* `204 - No Content`：标签删除成功。

**示例：**

<details>

<summary>AWS CLI</summary>

```console
$ aws --profile alluxio-s3 --endpoint "http://localhost:29998/" s3api get-bucket-tagging \
  --bucket=testbucket
{
    "TagSet": [
        {
            "Key": "key1",
            "Value": "val1"
        },
        {
            "Key": "key2",
            "Value": "val2"
        }
    ]
}

$ aws --profile alluxio-s3 --endpoint "http://localhost:29998/" s3api delete-bucket-tagging \
  --bucket=testbucket

$ aws --profile alluxio-s3 --endpoint "http://localhost:29998/" s3api get-bucket-tagging \
  --bucket=testbucket
{
    "TagSet": []
}
```

</details>

<details>

<summary>REST 客户端</summary>

```console
$ curl -i -H "Authorization: AWS4-HMAC-SHA256 Credential=testuser/..." \
  -X GET "http://localhost:29998/testbucket?tagging"
HTTP/1.1 200 OK
Date: Tue, 03 May 2022 23:31:07 GMT
Content-Type: application/xml
Content-Length: 124
Server: Jetty(9.4.43.v20210629)

<Tagging>
  <TagSet>
    <Tag>
      <Key>key1</Key>
      <Value>val1</Value>
    </Tag>
    <Tag>
      <Key>key2</Key>
      <Value>val2</Value>
    </Tag>
  </TagSet>
</Tagging>

$ curl -i -H "Authorization: AWS4-HMAC-SHA256 Credential=testuser/..." \
  -X DELETE "http://localhost:29998/testbucket?tagging"
HTTP/1.1 204 No Content
Date: Tue, 03 May 2022 23:32:26 GMT
Server: Jetty(9.4.43.v20210629)

$ curl -i -H "Authorization: AWS4-HMAC-SHA256 Credential=testuser/..." \
  -X GET "http://localhost:29998/testbucket?tagging"
HTTP/1.1 200 OK
Date: Tue, 03 May 2022 23:32:27 GMT
Content-Type: application/xml
Content-Length: 28
Server: Jetty(9.4.43.v20210629)

<Tagging><TagSet/></Tagging>
```

</details>

### 对象操作

#### GetObject

从存储桶中检索对象。

**方法：** `GET`

**路径：** `/{bucket}/{key}`

**响应：**

* `200 - OK`：对象数据在响应体中返回。

**示例：**

<details>

<summary>AWS CLI</summary>

```console
$ aws --profile alluxio-s3 --endpoint "http://localhost:29998/" s3api get-object \
  --bucket=testbucket --key=test.txt /tmp/test.txt
{
    "LastModified": "2022-05-03T18:55:01+00:00",
    "ContentLength": 27040,
    "ETag": "0cc175b9c0f1b6a831c399e269772661",
    "ContentType": "application/octet-stream",
    "Metadata": {}
}

$ stat /tmp/test.txt
  File: /tmp/test.txt
  Size: 27040       Blocks: 56         IO Block: 4096   regular file
  ...
```

</details>

<details>

<summary>REST 客户端</summary>

```console
$ curl -i -H "Authorization: AWS4-HMAC-SHA256 Credential=testuser/..." \
  -X GET http://localhost:29998/testbucket/test.txt
HTTP/1.1 200 OK
Date: Tue, 03 May 2022 22:59:43 GMT
Last-Modified: Tue, 03 May 2022 21:47:36 GMT
ETag: 0cc175b9c0f1b6a831c399e269772661
Content-Type: application/octet-stream
Content-Length: 27040
Server: Jetty(9.4.43.v20210629)

................. 文件内容 .................
```

</details>

***

#### PutObject

向存储桶添加对象。

**方法：** `PUT`

**路径：** `/{bucket}/{key}`

**请求体：** 对象内容。

**响应：**

* `200 - OK`：对象上传成功。

**示例：**

<details>

<summary>AWS CLI</summary>

```console
$ aws --profile alluxio-s3 --endpoint "http://localhost:29998/" s3api put-object \
  --bucket=testbucket --key=test.txt --body="${ALLUXIO_HOME}/LICENSE"
{
    "ETag": "911df44b7ff57801ca8d74568e4ebfbe"
}

$ aws --profile alluxio-s3 --endpoint "http://localhost:29998/" s3api list-objects \
  --bucket=testbucket
{
    "Contents": [
        {
            "Key": "test.txt",
            "LastModified": "2022-05-03T11:35:59.243000+00:00",
            "Size": 27040
        }
    ]
}
```

</details>

<details>

<summary>REST 客户端</summary>

```console
$ curl -i -H "Authorization: AWS4-HMAC-SHA256 Credential=testuser/..." \
  -X PUT http://localhost:29998/testbucket/test.txt -T "${ALLUXIO_HOME}/LICENSE"
HTTP/1.1 100 Continue

HTTP/1.1 200 OK
Date: Tue, 03 May 2022 21:47:36 GMT
ETag: 911df44b7ff57801ca8d74568e4ebfbe
Content-Length: 0
Server: Jetty(9.4.43.v20210629)

$ curl -i -H "Authorization: AWS4-HMAC-SHA256 Credential=testuser/..." \
  -X GET http://localhost:29998/testbucket
HTTP/1.1 200 OK
Date: Tue, 03 May 2022 21:47:44 GMT
Content-Type: application/xml
Content-Length: 318
Server: Jetty(9.4.43.v20210629)

<ListBucketResult>
  <version2>false</version2>
  <Contents>
    <Key>test.txt</Key>
    <Size>27040</Size>
    <LastModified>2022-05-03T14:47:36.600Z</LastModified>
  </Contents>
  <Marker/>
  <IsTruncated>false</IsTruncated>
  <Prefix/>
  <Name>testbucket</Name>
  <MaxKeys>1000</MaxKeys>
  <EncodingType>url</EncodingType>
</ListBucketResult>
```

</details>

***

#### CopyObject

创建已存储在 Alluxio 中的对象的副本。

**方法：** `PUT`

**路径：** `/{bucket}/{key}`

**请求头：**

* `x-amz-copy-source`：源存储桶和键的名称，用斜杠（`/`）分隔。

**响应：**

* `200 - OK`：返回一个包含复制操作结果的 XML 文档。

**示例：**

<details>

<summary>AWS CLI</summary>

```console
$ aws --profile alluxio-s3 --endpoint "http://localhost:29998/" s3api copy-object \
  --copy-source=testbucket/test.txt --bucket=testbucket --key=test_copy.txt
{
    "CopyObjectResult": {
        "ETag": "911df44b7ff57801ca8d74568e4ebfbe",
        "LastModified": "2022-05-03T11:37:16.015000+00:00"
    }
}

$ aws --profile alluxio-s3 --endpoint "http://localhost:29998/" s3api list-objects \
  --bucket=testbucket
{
    "Contents": [
        {
            "Key": "test.txt",
            "LastModified": "2022-05-03T11:35:59.243000+00:00",
            "Size": 27040
        },
        {
            "Key": "test_copy.txt",
            "LastModified": "2022-05-03T11:37:16.185000+00:00",
            "Size": 27040
        }
    ]
}
```

</details>

<details>

<summary>REST 客户端</summary>

```console
$ curl -i -H "Authorization: AWS4-HMAC-SHA256 Credential=testuser/..." \
  -H "x-amz-copy-source: testbucket/test.txt" \
  -X PUT http://localhost:29998/testbucket/test_copy.txt
HTTP/1.1 200 OK
Date: Tue, 03 May 2022 21:50:07 GMT
Content-Type: application/xml
Content-Length: 135
Server: Jetty(9.4.43.v20210629)

<CopyObjectResult>
  <ETag>911df44b7ff57801ca8d74568e4ebfbe</ETag>
  <LastModified>2022-05-03T14:50:07.781Z</LastModified>
</CopyObjectResult>

$ curl -i -H "Authorization: AWS4-HMAC-SHA256 Credential=testuser/..." \
  -X GET http://localhost:29998/testbucket
HTTP/1.1 200 OK
Date: Tue, 03 May 2022 21:50:26 GMT
Content-Type: application/xml
Content-Length: 434
Server: Jetty(9.4.43.v20210629)

<ListBucketResult>
  <version2>false</version2>
  <Contents>
    <Key>test.txt</Key>
    <Size>27040</Size>
    <LastModified>2022-05-03T14:47:36.600Z</LastModified>
  </Contents>
  <Contents>
    <Key>test_copy.txt</Key>
    <Size>27040</Size>
    <LastModified>2022-05-03T14:50:07.790Z</LastModified>
  </Contents>
  <Marker/>
  <IsTruncated>false</IsTruncated>
  <Prefix/>
  <Name>testbucket</Name>
  <MaxKeys>1000</MaxKeys>
  <EncodingType>url</EncodingType>
</ListBucketResult>
```

</details>

***

#### DeleteObject

从存储桶中删除对象。

**方法：** `DELETE`

**路径：** `/{bucket}/{key}`

**响应：**

* `204 - No Content`：对象删除成功。

**示例：**

<details>

<summary>AWS CLI</summary>

```console
$ aws --profile alluxio-s3 --endpoint "http://localhost:29998/" s3api list-objects-v2 \
  --bucket=testbucket
{
    "Contents": [
        {
            "Key": "temp.txt",
            "LastModified": "2022-05-03T11:55:01.925000+00:00",
            "Size": 27040
        },
        {
            "Key": "test.txt",
            "LastModified": "2022-05-03T11:54:19.698000+00:00",
            "Size": 27040
        }
    ]
}

$ aws --profile alluxio-s3 --endpoint "http://localhost:29998/" s3api delete-object \
  --bucket=testbucket --key=temp.txt

$ aws --profile alluxio-s3 --endpoint "http://localhost:29998/" s3api list-objects-v2 \
  --bucket=testbucket
{
    "Contents": [
        {
            "Key": "test.txt",
            "LastModified": "2022-05-03T11:55:01.925000+00:00",
            "Size": 27040
        }
    ]
}
```

</details>

<details>

<summary>REST 客户端</summary>

```console
$ curl -i -H "Authorization: AWS4-HMAC-SHA256 Credential=testuser/..." \
  -X GET http://localhost:29998/testbucket
HTTP/1.1 200 OK
Date: Tue, 03 May 2022 21:59:27 GMT
Content-Type: application/xml
Content-Length: 540
Server: Jetty(9.4.43.v20210629)

<ListBucketResult>
  <version2>false</version2>
  <Contents>
    <Key>temp.txt</Key>
    <Size>27040</Size>
    <LastModified>2022-05-03T14:50:07.790Z</LastModified>
  </Contents>
  <Contents>
    <Key>test.txt</Key>
    <Size>27040</Size>
    <LastModified>2022-05-03T14:47:36.600Z</LastModified>
  </Contents>
  <Marker/>
  <IsTruncated>false</IsTruncated>
  <Prefix/>
  <Name>testbucket</Name>
  <MaxKeys>1000</MaxKeys>
  <EncodingType>url</EncodingType>
</ListBucketResult>

$ curl -i -H "Authorization: AWS4-HMAC-SHA256 Credential=testuser/..." \
  -X DELETE http://localhost:29998/testbucket/temp.txt
HTTP/1.1 204 No Content
Date: Tue, 03 May 2022 22:01:56 GMT
Server: Jetty(9.4.43.v20210629)

$ curl -i -H "Authorization: AWS4-HMAC-SHA256 Credential=testuser/..." \
  -X GET http://localhost:29998/testbucket
HTTP/1.1 200 OK
Date: Tue, 03 May 2022 22:01:59 GMT
Content-Type: application/xml
Content-Length: 318
Server: Jetty(9.4.43.v20210629)

<ListBucketResult>
  <version2>false</version2>
  <Contents>
    <Key>test.txt</Key>
    <Size>27040</Size>
    <LastModified>2022-05-03T14:47:36.600Z</LastModified>
  </Contents>
  <Marker/>
  <IsTruncated>false</IsTruncated>
  <Prefix/>
  <Name>testbucket</Name>
  <MaxKeys>1000</MaxKeys>
  <EncodingType>url</EncodingType>
</ListBucketResult>
```

</details>

***

#### DeleteObjects

在单个请求中从存储桶中删除多个对象。

**方法：** `POST`

**路径：** `/{bucket}?delete`

**请求体：** 一个 XML 文档，指定要删除的对象的键。

```xml
<Delete>
  <Object>
    <Key>key_1</Key>
  </Object>
  <Object>
    <Key>key_2</Key>
  </Object>
  ...
</Delete>
```

**响应：**

* `200 - OK`：返回一个 XML 文档，其中包含每个对象的删除操作结果。

**示例：**

<details>

<summary>AWS CLI</summary>

```console
$ aws --profile alluxio-s3 --endpoint "http://localhost:29998/" s3api list-objects-v2 \
  --bucket=tempbucket
{
    "Contents": [
        {
            "Key": "foo.txt",
            "LastModified": "2022-05-03T11:57:00.767000+00:00",
            "Size": 27040
        },
        {
            "Key": "temp.txt",
            "LastModified": "2022-05-03T11:56:11.245000+00:00",
            "Size": 27040
        },
        {
            "Key": "temp2.txt",
            "LastModified": "2022-05-03T11:56:31.414000+00:00",
            "Size": 27040
        }
    ]
}

$ aws --profile alluxio-s3 --endpoint "http://localhost:29998/" s3api delete-objects \
  --bucket=tempbucket --delete="Objects=[{Key=temp.txt},{Key=temp2.txt}]"

$ aws --profile alluxio-s3 --endpoint "http://localhost:29998/" s3api list-objects-v2 \
  --bucket=tempbucket
{
    "Contents": [
        {
            "Key": "foo.txt",
            "LastModified": "2022-05-03T11:57:00.767000+00:00",
            "Size": 27040
        }
    ]
}
```

</details>

<details>

<summary>REST Client</summary>

```console
$ curl -i -H "Authorization: AWS4-HMAC-SHA256 Credential=testuser/..." \
  -X GET http://localhost:29998/tempbucket
HTTP/1.1 200 OK
Date: Tue, 03 May 2022 21:59:27 GMT
Content-Type: application/xml
Content-Length: 540
Server: Jetty(9.4.43.v20210629)

<ListBucketResult>
  <version2>false</version2>
  <Contents>
    <Key>foo.txt</Key>
    <Size>27040</Size>
    <LastModified>2022-05-03T14:59:05.906Z</LastModified>
  </Contents>
  <Contents>
    <Key>temp.txt</Key>
    <Size>27040</Size>
    <LastModified>2022-05-03T14:58:58.204Z</LastModified>
  </Contents>
  <Contents>
    <Key>temp2.txt</Key>
    <Size>27040</Size>
    <LastModified>2022-05-03T14:59:01.987Z</LastModified>
  </Contents>
  <Marker/>
  <IsTruncated>false</IsTruncated>
  <Prefix/>
  <Name>tempbucket</Name>
  <MaxKeys>1000</MaxKeys>
  <EncodingType>url</EncodingType>
</ListBucketResult>

$ cat delete.xml
<Delete xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
  <Object>
    <Key>temp.txt</Key>
  </Object>
  <Object>
    <Key>temp2.txt</Key>
  </Object>
  <Quiet>false</Quiet>
</Delete>

$ curl -i -H "Authorization: AWS4-HMAC-SHA256 Credential=testuser/..." \
  -H "Content-Type: application/xml" \
  -X POST --data "@delete.xml" "http://localhost:29998/testbucket?delete"
HTTP/1.1 200 OK
Date: Tue, 03 May 2022 22:56:17 GMT
Content-Type: application/xml
Content-Length: 208
Server: Jetty(9.4.43.v20210629)

<DeleteResult>
  <Deleted>
    <Key>temp2.txt</Key>
    <DeleteMarker/>
    <DeleteMarkerVersionId/>
    <VersionId/>
  </Deleted>
  <Deleted>
    <Key>temp.txt</Key>
    <DeleteMarker/>
    <DeleteMarkerVersionId/>
    <VersionId/>
  </Deleted>
</DeleteResult>

$ curl -i -H "Authorization: AWS4-HMAC-SHA256 Credential=testuser/..." \
  -X GET http://localhost:29998/tempbucket
HTTP/1.1 200 OK
Date: Tue, 03 May 2022 22:28:31 GMT
Content-Type: application/xml
Content-Length: 317
Server: Jetty(9.4.43.v20210629)

<ListBucketResult>
  <version2>false</version2>
  <Contents>
    <Key>foo.txt</Key>
    <Size>27040</Size>
    <LastModified>2022-05-03T14:59:05.906Z</LastModified>
  </Contents>
  <Marker/>
  <IsTruncated>false</IsTruncated>
  <Prefix/>
  <Name>tempbucket</Name>
  <MaxKeys>1000</MaxKeys>
  <EncodingType>url</EncodingType>
</ListBucketResult>
```

</details>

***

#### HeadObject

从对象中检索元数据，而不返回对象本身。

**方法:** `HEAD`

**路径:** `/{bucket}/{key}`

**响应:**

* `200 - OK`: 元数据将在响应头中返回。

**示例:**

<details>

<summary>AWS CLI</summary>

```console
$ aws --profile alluxio-s3 --endpoint "http://localhost:29998/" s3api head-object \
  --bucket=testbucket --key=test.txt
{
    "LastModified": "2022-05-03T18:55:01+00:00",
    "ContentLength": 27040,
    "ETag": "0cc175b9c0f1b6a831c399e269772661",
    "ContentType": "application/octet-stream",
    "Metadata": {}
}
```

</details>

<details>

<summary>REST Client</summary>

```console
$ curl -i -H "Authorization: AWS4-HMAC-SHA256 Credential=testuser/..." \
  --head http://localhost:29998/testbucket/test.txt
HTTP/1.1 200 OK
Date: Tue, 03 May 2022 21:54:22 GMT
Last-Modified: Tue, 03 May 2022 21:47:36 GMT
ETag: 0cc175b9c0f1b6a831c399e269772661
Content-Type: application/octet-stream
Content-Length: 27040
Server: Jetty(9.4.43.v20210629)
```

</details>

***

#### ListObjects

返回存储桶中部分或全部（最多 1,000 个）对象。

**方法:** `GET`

**路径:** `/{bucket}`

**响应:**

* `200 - OK`: 返回一个包含对象列表的 XML 文档。

**示例:**

<details>

<summary>AWS CLI</summary>

```console
$ aws --profile alluxio-s3 --endpoint "http://localhost:29998/" s3api list-objects \
  --bucket=testbucket
{
    "Contents": [
        {
            "Key": "test.txt",
            "LastModified": "2022-05-03T11:35:59.243000+00:00",
            "Size": 27040
        },
        {
            "Key": "test_copy.txt",
            "LastModified": "2022-05-03T11:37:16.185000+00:00",
            "Size": 27040
        }
    ]
}
```

</details>

<details>

<summary>REST Client</summary>

```console
$ curl -i -H "Authorization: AWS4-HMAC-SHA256 Credential=testuser/..." \
  -X GET http://localhost:29998/testbucket
HTTP/1.1 200 OK
Date: Tue, 03 May 2022 21:50:26 GMT
Content-Type: application/xml
Content-Length: 434
Server: Jetty(9.4.43.v20210629)

<ListBucketResult>
  <version2>false</version2>
  <Contents>
    <Key>test.txt</Key>
    <Size>27040</Size>
    <LastModified>2022-05-03T14:47:36.600Z</LastModified>
  </Contents>
  <Contents>
    <Key>test_copy.txt</Key>
    <Size>27040</Size>
    <LastModified>2022-05-03T14:50:07.790Z</LastModified>
  </Contents>
  <Marker/>
  <IsTruncated>false</IsTruncated>
  <Prefix/>
  <Name>testbucket</Name>
  <MaxKeys>1000</MaxKeys>
  <EncodingType>url</EncodingType>
</ListBucketResult>
```

</details>

***

#### ListObjectsV2

返回存储桶中部分或全部（最多 1,000 个）对象。这是 `ListObjects`的新版本。

**方法:** `GET`

**路径:** `/{bucket}?list-type=2`

**响应:**

* `200 - OK`: 返回一个包含对象列表的 XML 文档。

**示例:**

<details>

<summary>AWS CLI</summary>

```console
$ aws --profile alluxio-s3 --endpoint "http://localhost:29998/" s3api list-objects-v2 \
  --bucket=testbucket
{
    "Contents": [
        {
            "Key": "test.txt",
            "LastModified": "2022-05-03T11:35:59.243000+00:00",
            "Size": 27040
        },
        {
            "Key": "test_copy.txt",
            "LastModified": "2022-05-03T11:37:16.185000+00:00",
            "Size": 27040
        }
    ]
}
```

</details>

<details>

<summary>REST Client</summary>

```console
$ curl -i -H "Authorization: AWS4-HMAC-SHA256 Credential=testuser/..." \
  -X GET "http://localhost:29998/testbucket?list-type=2"
HTTP/1.1 200 OK
Date: Tue, 03 May 2022 21:56:20 GMT
Content-Type: application/xml
Content-Length: 438
Server: Jetty(9.4.43.v20210629)

<ListBucketResult>
  <version2>true</version2>
  <Contents>
    <Key>test.txt</Key>
    <Size>27040</Size>
    <LastModified>2022-05-03T14:47:36.600Z</LastModified>
  </Contents>
  <Contents>
    <Key>test_copy.txt</Key>
    <Size>27040</Size>
    <LastModified>2022-05-03T14:50:07.790Z</LastModified>
  </Contents>
  <IsTruncated>false</IsTruncated>
  <Prefix/>
  <KeyCount>2</KeyCount>
  <Name>testbucket</Name>
  <MaxKeys>1000</MaxKeys>
  <EncodingType>url</EncodingType>
</ListBucketResult>
```

</details>

***

#### GetObjectTagging

检索与对象关联的标签。

**方法:** `GET`

**路径:** `/{bucket}/{key}?tagging`

**响应:**

* `200 - OK`: 返回一个包含标签集合的 XML 文档。

**示例:**

<details>

<summary>AWS CLI</summary>

```console
$ aws --profile alluxio-s3 --endpoint "http://localhost:29998/" s3api get-object-tagging \
  --bucket=testbucket --key=test.txt
{
    "TagSet": [
        {
            "Key": "key1",
            "Value": "val1"
        },
        {
            "Key": "key2",
            "Value": "val2"
        }
    ]
}
```

</details>

<details>

<summary>REST Client</summary>

```console
$ curl -i -H "Authorization: AWS4-HMAC-SHA256 Credential=testuser/..." \
  -X GET "http://localhost:29998/testbucket/test.txt?tagging"
HTTP/1.1 200 OK
Date: Tue, 03 May 2022 23:35:58 GMT
Content-Type: application/octet-stream
Content-Length: 126
Server: Jetty(9.4.43.v20210629)

<Tagging>
  <TagSet>
    <Tag>
      <Key>key1</Key>
      <Value>val1</Value>
    </Tag>
    <Tag>
      <Key>key2</Key>
      <Value>val2</Value>
    </Tag>
  </TagSet>
</Tagging>
```

</details>

***

#### PutObjectTagging

向现有对象添加一组标签。

**方法:** `PUT`

**路径:** `/{bucket}/{key}?tagging`

**请求体:** 包含标签集合的 XML 文档。

**响应:**

* `200 - OK`: 标签已成功添加。

**示例:**

<details>

<summary>AWS CLI</summary>

```console
$ aws --profile alluxio-s3 --endpoint "http://localhost:29998/" s3api get-object-tagging \
  --bucket=testbucket --key=test.txt
{
    "TagSet": []
}

$ aws --profile alluxio-s3 --endpoint "http://localhost:29998/" s3api put-object-tagging \
  --bucket=testbucket --key=test.txt --tagging='TagSet=[{Key=key1,Value=val1},{Key=key2,Value=val2}]'

$ aws --profile alluxio-s3 --endpoint "http://localhost:29998/" s3api get-object-tagging \
  --bucket=testbucket --key=test.txt
{
    "TagSet": [
        {
            "Key": "key1",
            "Value": "val1"
        },
        {
            "Key": "key2",
            "Value": "val2"
        }
    ]
}
```

</details>

<details>

<summary>REST Client</summary>

```console
$ curl -i -H "Authorization: AWS4-HMAC-SHA256 Credential=testuser/..." \
  -X GET "http://localhost:29998/testbucket/test.txt?tagging"
HTTP/1.1 200 OK
Date: Tue, 03 May 2022 23:30:25 GMT
Content-Type: application/xml
Content-Length: 28
Server: Jetty(9.4.43.v20210629)

<Tagging><TagSet/></Tagging>

$ cat tags.xml
<Tagging>
  <TagSet>
    <Tag>
      <Key>key1</Key>
      <Value>val1</Value>
    </Tag>
    <Tag>
      <Key>key2</Key>
      <Value>val2</Value>
    </Tag>
  </TagSet>
</Tagging>

$ curl -i -H "Authorization: AWS4-HMAC-SHA256 Credential=testuser/..." \
  -H "Content-Type: application/xml" \
  -X PUT "http://localhost:29998/testbucket/test.txt?tagging" --data-binary "@tags.xml"
HTTP/1.1 200 OK
Date: Tue, 03 May 2022 23:35:28 GMT
Content-Length: 0
Server: Jetty(9.4.43.v20210629)

$ curl -i -H "Authorization: AWS4-HMAC-SHA256 Credential=testuser/..." \
  -X GET "http://localhost:29998/testbucket/test.txt?tagging"
HTTP/1.1 200 OK
Date: Tue, 03 May 2022 23:35:58 GMT
Content-Type: application/octet-stream
Content-Length: 126
Server: Jetty(9.4.43.v20210629)

<Tagging>
  <TagSet>
    <Tag>
      <Key>key1</Key>
      <Value>val1</Value>
    </Tag>
    <Tag>
      <Key>key2</Key>
      <Value>val2</Value>
    </Tag>
  </TagSet>
</Tagging>
```

</details>

***

#### DeleteObjectTagging

从对象中删除标签。

**方法:** `DELETE`

**路径:** `/{bucket}/{key}?tagging`

**响应:**

* `204 - No Content`: 标签已成功删除。

**示例:**

<details>

<summary>AWS CLI</summary>

```console
$ aws --profile alluxio-s3 --endpoint "http://localhost:29998/" s3api get-object-tagging \
  --bucket=testbucket --key=test.txt
{
    "TagSet": [
        {
            "Key": "key1",
            "Value": "val1"
        },
        {
            "Key": "key2",
            "Value": "val2"
        }
    ]
}

$ aws --profile alluxio-s3 --endpoint "http://localhost:29998/" s3api delete-object-tagging \
  --bucket=testbucket --key=test.txt

$ aws --profile alluxio-s3 --endpoint "http://localhost:29998/" s3api get-object-tagging \
  --bucket=testbucket --key=test.txt
{
    "TagSet": []
}
```

</details>

<details>

<summary>REST Client</summary>

```console
$ curl -i -H "Authorization: AWS4-HMAC-SHA256 Credential=testuser/..." \
  -X GET "http://localhost:29998/testbucket/test.txt?tagging"
HTTP/1.1 200 OK
Date: Tue, 03 May 2022 23:35:58 GMT
Content-Type: application/octet-stream
Content-Length: 126
Server: Jetty(9.4.43.v20210629)

<Tagging>
  <TagSet>
    <Tag>
      <Key>key1</Key>
      <Value>val1</Value>
    </Tag>
    <Tag>
      <Key>key2</Key>
      <Value>val2</Value>
    </Tag>
  </TagSet>
</Tagging>

$ curl -i -H "Authorization: AWS4-HMAC-SHA256 Credential=testuser/..." \
  -X DELETE "http://localhost:29998/testbucket/test.txt?tagging"
HTTP/1.1 204 No Content
Date: Tue, 03 May 2022 23:37:46 GMT
Server: Jetty(9.4.43.v20210629)

$ curl -i -H "Authorization: AWS4-HMAC-SHA256 Credential=testuser/..." \
  -X GET "http://localhost:29998/testbucket/test.txt?tagging"
HTTP/1.1 200 OK
Date: Tue, 03 May 2022 23:37:47 GMT
Content-Type: application/octet-stream
Content-Length: 28
Server: Jetty(9.4.43.v20210629)

<Tagging><TagSet/></Tagging>
```

</details>

### 分片上传操作

#### CreateMultipartUpload

启动一个分片上传并返回上传 ID。

**方法:** `POST`

**路径:** `/{bucket}/{key}?uploads`

**响应:**

* `200 - OK`: 返回一个包含 `UploadId` 的 XML 文档。

**示例:**

<details>

<summary>AWS CLI</summary>

```console
$ aws --profile alluxio-s3 --endpoint "http://localhost:29998/" s3api create-multipart-upload \
  --bucket=testbucket --key=multipart.txt
{
    "Bucket": "testbucket",
    "Key": "multipart.txt",
    "UploadId": "6367cf96-ea4e-4447-b931-c5bc91200375"
}
```

</details>

<details>

<summary>REST Client</summary>

```console
$ curl -i -H "Authorization: AWS4-HMAC-SHA256 Credential=testuser/..." \
  -X POST "http://localhost:29998/testbucket/multipart.txt?uploads"
HTTP/1.1 200 OK
Date: Tue, 03 May 2022 23:41:26 GMT
Content-Type: application/xml
Content-Length: 147
Server: Jetty(9.4.43.v20210629)

<InitiateMultipartUploadResult>
  <Bucket>testbucket</Bucket>
  <Key>multipart.txt</Key>
  <UploadId>6367cf96-ea4e-4447-b931-c5bc91200375</UploadId>
</InitiateMultipartUploadResult>
```

</details>

***

#### UploadPart

在分片上传中上传一个分片。

**方法:** `PUT`

**路径:** `/{bucket}/{key}`

**查询参数:**

* `partNumber`: 正在上传的分片编号，为 1 到 10,000 之间的正整数。
* `uploadId`: 分片上传的上传 ID。

**请求体:** 分片的内容。

**响应:**

* `200 - OK`: 分片上传成功。

**示例:**

<details>

<summary>AWS CLI</summary>

```console
$ aws --profile alluxio-s3 --endpoint "http://localhost:29998/" s3api upload-part \
  --bucket=testbucket --key=multipart.txt --upload-id=6367cf96-ea4e-4447-b931-c5bc91200375 --part-number=1 --body="${ALLUXIO_HOME}/LICENSE"
{
    "ETag": "911df44b7ff57801ca8d74568e4ebfbe"
}

$ aws --profile alluxio-s3 --endpoint "http://localhost:29998/" s3api list-parts \
  --bucket=testbucket --key=multipart.txt --upload-id=6367cf96-ea4e-4447-b931-c5bc91200375
{
    "Parts": [
        {
            "PartNumber": 1,
            "LastModified": "2022-05-03T12:56:27.775000+00:00",
            "ETag": "",
            "Size": 27040
        }
    ],
    "ChecksumAlgorithm": null,
    "Initiator": null,
    "Owner": null,
    "StorageClass": "STANDARD"
}
```

</details>

<details>

<summary>REST Client</summary>

```console
$ curl -i -H "Authorization: AWS4-HMAC-SHA256 Credential=testuser/..." \
  -X PUT -T "${ALLUXIO_HOME}/LICENSE" "http://localhost:29998/testbucket/multipart.txt?uploadId=6367cf96-ea4e-4447-b931-c5bc91200375&partNumber=1"
HTTP/1.1 100 Continue

HTTP/1.1 200 OK
Date: Tue, 03 May 2022 23:51:19 GMT
ETag: "911df44b7ff57801ca8d74568e4ebfbe"
Content-Length: 0
Server: Jetty(9.4.43.v20210629)

$ aws --profile alluxio-s3 --endpoint "http://localhost:29998/" s3api list-parts \
  --bucket=testbucket --key=multipart_copy.txt --upload-id=6367cf96-ea4e-4447-b931-c5bc91200375
{
    "Parts": [
        {
            "PartNumber": 1,
            "LastModified": "2022-05-03T13:00:13.584000+00:00",
            "ETag": "",
            "Size": 27040
        }
    ],
    "ChecksumAlgorithm": null,
    "Initiator": null,
    "Owner": null,
    "StorageClass": "STANDARD"
}
```

</details>

***

#### UploadPartCopy

通过从现有对象复制数据作为数据源来上传分片。

**方法:** `PUT`

**路径:** `/{bucket}/{key}`

**查询参数:**

* `partNumber`: 正在上传的分片编号。
* `uploadId`: 分片上传的上传 ID。

**请求头:**

* `x-amz-copy-source`: 源存储桶名称和对象键。

**响应:**

* `200 - OK`: 分片复制成功。

**示例:**

<details>

<summary>AWS CLI</summary>

```console
$ aws --profile alluxio-s3 --endpoint "http://localhost:29998/" s3api upload-part-copy \
  --bucket=testbucket --key=object --upload-id=6367cf96-ea4e-4447-b931-c5bc91200375 --part-number=1 --copy-source=testbucket/object
{
    "CopyPartResult": {
        "ETag": "0cc175b9c0f1b6a831c399e269772661"
    }
}

$ aws --profile alluxio-s3 --endpoint "http://localhost:29998/" s3api list-parts \
  --bucket=testbucket --key=object --upload-id=6367cf96-ea4e-4447-b931-c5bc91200375
{
    "Parts": [
        {
            "PartNumber": 1,
            "LastModified": "2022-07-01T11:27:48.942000+00:00",
            "ETag": "",
            "Size": 1
        }
    ],
    "ChecksumAlgorithm": null,
    "Initiator": null,
    "Owner": null,
    "StorageClass": "STANDARD"
}
```

</details>

<details>

<summary>REST Client</summary>

```console
$ curl -i -H "Authorization: AWS4-HMAC-SHA256 Credential=testuser/..." \
  -H "x-amz-copy-source: testbucket/object" \
  -X PUT 'http://localhost:29998/testbucket/object?uploadId=6367cf96-ea4e-4447-b931-c5bc91200375&partNumber=1'
HTTP/1.1 200 OK
Date: Fri, 01 Jul 2022 18:31:34 GMT
Content-Type: application/xml
Content-Length: 78
Server: Jetty(9.4.46.v20220331)

<CopyPartResult><ETag>0cc175b9c0f1b6a831c399e269772661</ETag></CopyPartResult>
```

</details>

***

#### ListParts

列出特定分片上传中已上传的分片。

**方法:** `GET`

**路径:** `/{bucket}/{key}`

**查询参数:**

* `uploadId`: 分片上传的上传 ID。

**响应:**

* `200 - OK`: 返回包含分片列表的 XML 文档。

**示例:**

<details>

<summary>AWS CLI</summary>

```console
$ aws --profile alluxio-s3 --endpoint "http://localhost:29998/" s3api list-parts \
  --bucket=testbucket --key=multipart.txt --upload-id=6367cf96-ea4e-4447-b931-c5bc91200375
{
    "Parts": [
        {
            "PartNumber": 1,
            "LastModified": "2022-05-03T12:56:27.775000+00:00",
            "ETag": "",
            "Size": 27040
        }
    ],
    "ChecksumAlgorithm": null,
    "Initiator": null,
    "Owner": null,
    "StorageClass": "STANDARD"
}
```

</details>

<details>

<summary>REST Client</summary>

```console
$ curl -i -H "Authorization: AWS4-HMAC-SHA256 Credential=testuser/..." \
  -X GET "http://localhost:29998/testbucket/multipart.txt?uploadId=6367cf96-ea4e-4447-b931-c5bc91200375"
HTTP/1.1 200 OK
Date: Tue, 03 May 2022 23:49:05 GMT
Content-Type: application/octet-stream
Content-Length: 314
Server: Jetty(9.4.43.v20210629)

<ListPartsResult>
  <Bucket>/testbucket</Bucket>
  <Key>multipart.txt</Key>
  <UploadId>6367cf96-ea4e-4447-b931-c5bc91200375</UploadId>
  <StorageClass>STANDARD</StorageClass>
  <IsTruncated>false</IsTruncated>
  <Part>
    <PartNumber>1</PartNumber>
    <LastModified>2022-05-03T16:48:56.602Z</LastModified>
    <ETag></ETag>
    <Size>27040</Size>
  </Part>
</ListPartsResult>
```

</details>

***

#### ListMultipartUploads

此操作列出正在进行的分片上传。

**方法:** `GET`

**路径:** `/{bucket}?uploads`

**响应:**

* `200 - OK`: 返回包含正在进行的分片上传列表的 XML 文档。

**示例:**

<details>

<summary>AWS CLI</summary>

```console
$ aws --profile alluxio-s3 --endpoint="http://localhost:39999/api/v1/s3" s3api list-multipart-uploads --bucket "testbucket"
{
    "Uploads": [
        {
            "UploadId": "c4cddf71-914a-4cee-b2af-8cfb7def7d04",
            "Key": "object",
            "Initiated": "2022-07-01T11:21:14.738000+00:00"
        },
        {
            "UploadId": "6367cf96-ea4e-4447-b931-c5bc91200375",
            "Key": "object",
            "Initiated": "2022-07-01T11:18:25.290000+00:00"
        },
        {
            "UploadId": "e111c33b-5c18-4ecd-b543-2849cdbbf22b",
            "Key": "object2",
            "Initiated": "2022-07-01T11:21:25.182000+00:00"
        }
    ]
}
```

</details>

<details>

<summary>REST Client</summary>

```console
$ curl -i -H "Authorization: AWS4-HMAC-SHA256 Credential=testuser/..." \
  -X GET "http://localhost:29998/testbucket?uploads"
HTTP/1.1 200 OK
Date: Fri, 01 Jul 2022 18:23:43 GMT
Content-Type: application/xml
Content-Length: 499
Server: Jetty(9.4.46.v20220331)

<ListMultipartUploadsResult>
  <Bucket>testbucket</Bucket>
  <Upload>
    <Key>object</Key>
    <UploadId>c4cddf71-914a-4cee-b2af-8cfb7def7d04</UploadId>
    <Initiated>2022-07-01T11:21:14.738Z</Initiated>
  </Upload>
  <Upload>
    <Key>object</Key>
    <UploadId>6367cf96-ea4e-4447-b931-c5bc91200375</UploadId>
    <Initiated>2022-07-01T11:18:25.290Z</Initiated>
  </Upload>
  <Upload>
    <Key>object2</Key>
    <UploadId>e111c33b-5c18-4ecd-b543-2849cdbbf22b</UploadId>
    <Initiated>2022-07-01T11:21:25.182Z</Initiated>
  </Upload>
</ListMultipartUploadsResult>
```

</details>

***

#### AbortMultipartUpload

中止分片上传。中止分片上传后，无法再使用该上传 ID 上传任何分片。

**方法:** `DELETE`

**路径:** `/{bucket}/{key}`

**查询参数:**

* `uploadId`: 要中止的分片上传 ID。

**响应:**

* `204 - No Content`: 分片上传已成功中止。

**示例:**

<details>

<summary>AWS CLI</summary>

```console
$ aws --profile alluxio-s3 --endpoint "http://localhost:29998/" s3api list-objects-v2 \
  --bucket=testbucket
{
    "Contents": [
        {
            "Key": "multipart_copy.txt_6367cf96-ea4e-4447-b931-c5bc91200375/",
            "LastModified": "2022-05-03T13:00:13.429000+00:00",
            "Size": 0
        },
        {
            "Key": "multipart_copy.txt_6367cf96-ea4e-4447-b931-c5bc91200375/1",
            "LastModified": "2022-05-03T13:00:13.584000+00:00",
            "Size": 27040
        },
        {
            "Key": "test.txt",
            "LastModified": "2022-05-03T11:55:01.925000+00:00",
            "Size": 27040
        }
    ]
}

$ aws --profile alluxio-s3 --endpoint "http://localhost:29998/" s3api abort-multipart-upload \
  --bucket=testbucket --key=multipart_copy.txt --upload-id=6367cf96-ea4e-4447-b931-c5bc91200375

$ % aws --profile alluxio-s3 --endpoint "http://localhost:29998/" s3api list-objects-v2 \
  --bucket=testbucket
{
    "Contents": [
        {
            "Key": "test.txt",
            "LastModified": "2022-05-03T11:55:01.925000+00:00",
            "Size": 27040
        }
    ]
}
```

</details>

<details>

<summary>REST Client</summary>

```console
$ curl -i -H "Authorization: AWS4-HMAC-SHA256 Credential=testuser/..." \
  -X GET "http://localhost:29998/testbucket"
HTTP/1.1 200 OK
Date: Tue, 03 May 2022 23:45:17 GMT
Content-Type: application/xml
Content-Length: 583
Server: Jetty(9.4.43.v20210629)

<ListBucketResult>
  <version2>false</version2>
  <Marker/>
  <Prefix/>
  <IsTruncated>false</IsTruncated>
  <Name>testbucket</Name>
  <Contents>
    <Key>multipart.txt_6367cf96-ea4e-4447-b931-c5bc91200375/</Key>
    <Size>0</Size>
    <LastModified>2022-05-03T16:44:17.490Z</LastModified>
  </Contents>
  <Contents>
    <Key>multipart.txt_6367cf96-ea4e-4447-b931-c5bc91200375/1</Key>
    <Size>27040</Size>
    <LastModified>2022-05-03T16:44:17.715Z</LastModified>
  </Contents>
  <Contents>
    <Key>test.txt</Key>
    <Size>27040</Size>
    <LastModified>2022-05-03T14:47:36.600Z</LastModified>
  </Contents>
  <MaxKeys>1000</MaxKeys>
  <EncodingType>url</EncodingType>
</ListBucketResult>

$ curl -i -H "Authorization: AWS4-HMAC-SHA256 Credential=testuser/..." \
  -X DELETE "http://localhost:29998/testbucket/multipart.txt?uploadId=6367cf96-ea4e-4447-b931-c5bc91200375"
HTTP/1.1 204 No Content
Date: Tue, 03 May 2022 23:45:30 GMT
Server: Jetty(9.4.43.v20210629)

$ curl -i -H "Authorization: AWS4-HMAC-SHA256 Credential=testuser/..." \
  -X GET "http://localhost:29998/testbucket"
HTTP/1.1 200 OK
Date: Tue, 03 May 2022 23:45:36 GMT
Content-Type: application/xml
Content-Length: 318
Server: Jetty(9.4.43.v20210629)

<ListBucketResult>
  <version2>false</version2>
  <Marker/>
  <Prefix/>
  <IsTruncated>false</IsTruncated>
  <Name>testbucket</Name>
  <Contents>
    <Key>test.txt</Key>
    <Size>27040</Size>
    <LastModified>2022-05-03T14:47:36.600Z</LastModified>
  </Contents>
  <MaxKeys>1000</MaxKeys>
  <EncodingType>url</EncodingType>
</ListBucketResult>
```

</details>

***

#### CompleteMultipartUpload

通过组装先前上传的分片完成分片上传。

**方法:** `POST`

**路径:** `/{bucket}/{key}`

**查询参数:**

* `uploadId`: 要完成的分片上传 ID。

**请求体:** 一个包含待组装分片列表的 XML 文档。

```xml
<CompleteMultipartUpload>
   <Part>
      <PartNumber>1</PartNumber>
   </Part>
   <Part>
      <PartNumber>2</PartNumber>
   </Part>
   ...
</CompleteMultipartUpload>
```

**响应:**

* `200 - OK`: 返回一个包含已完成对象信息的 XML 文档。

**示例:**

<details>

<summary>AWS CLI</summary>

```console
$ aws --profile alluxio-s3 --endpoint "http://localhost:29998/" s3api complete-multipart-upload \
  --bucket=testbucket --key=multipart.txt --upload-id=6367cf96-ea4e-4447-b931-c5bc91200375 \
  --multipart-upload="Parts=[{PartNumber=1},{PartNumber=2}]"
{
    "Location": "/testbucket/multipart.txt",
    "Bucket": "testbucket",
    "Key": "multipart.txt",
    "ETag": "911df44b7ff57801ca8d74568e4ebfbe"
}

$ aws --profile alluxio-s3 --endpoint "http://localhost:29998/" s3api head-object \
  --bucket=testbucket --key=multipart.txt
{
    "LastModified": "2022-05-03T20:01:43+00:00",
    "ContentLength": 27040,
    "ETag": "0cc175b9c0f1b6a831c399e269772661",
    "ContentType": "application/octet-stream",
    "Metadata": {}
}
```

</details>

<details>

<summary>REST Client</summary>

```console
$ cat complete_upload.xml

<CompleteMultipartUpload xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
   <Part>
      <PartNumber>1</PartNumber>
   </Part>
   <Part>
      <PartNumber>2</PartNumber>
   </Part>
</CompleteMultipartUpload>

$ curl -i -H "Authorization: AWS4-HMAC-SHA256 Credential=testuser/..." \
  -H "Content-Type: application/xml" -d "@complete_upload.xml" \
  -X POST "http://localhost:29998/testbucket/multipart.txt?uploadId=6367cf96-ea4e-4447-b931-c5bc91200375"

Date: Tue, 03 May 2022 23:59:17 GMT
Content-Type: text/xml;charset=utf-8
Transfer-Encoding: chunked
Server: Jetty(9.4.43.v20210629)

<CompleteMultipartUploadResult>
  <Location>/testbucket/multipart.txt</Location>
  <Bucket>testbucket</Bucket>
  <Key>multipart.txt</Key>
  <ETag>911df44b7ff57801ca8d74568e4ebfbe</ETag>
  <Code/>
  <Message/>
</CompleteMultipartUploadResult>

$ curl -i -H "Authorization: AWS4-HMAC-SHA256 Credential=testuser/..." \
  --head "http://localhost:29998/testbucket/multipart.txt"
HTTP/1.1 200 OK
Date: Wed, 04 May 2022 00:00:40 GMT
Last-Modified: Tue, 03 May 2022 23:59:18 GMT
ETag: 0cc175b9c0f1b6a831c399e269772661
Content-Type: application/octet-stream
Content-Length: 27040
Server: Jetty(9.4.43.v20210629)
```

</details>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://documentation.alluxio.io/ee-ai-cn/ai-3.8-15.1.x-cn/reference/s3-api-usage.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
