

 適用於 JavaScript 的 AWS SDK v2 已end-of-support。我們建議您遷移至 [適用於 JavaScript 的 AWS SDK v3](https://docs.aws.amazon.com//sdk-for-javascript/v3/developer-guide/)。如需如何遷移的其他詳細資訊和資訊，請參閱此[公告](https://aws.amazon.com/blogs//developer/announcing-end-of-support-for-aws-sdk-for-javascript-v2/)。

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 從瀏覽器上傳相片至 Amazon S3
<a name="s3-example-photo-album"></a>

![JavaScript code example that applies to browser execution](http://docs.aws.amazon.com/zh_tw/sdk-for-javascript/v2/developer-guide/images/browsericon.png)

**此瀏覽器程式碼範例顯示：**
+ 如何建立瀏覽器應用程式，允許使用者在 Amazon S3 儲存貯體中建立相簿，並將相片上傳至相簿。

## 使用案例
<a name="s3-example-photo-album-scenario"></a>

在此範例中，簡單的 HTML 頁面提供以瀏覽器為基礎的應用程式，用於在 Amazon S3 儲存貯體中建立相簿，您可以將相片上傳至其中。該應用程式可讓您刪除新增的相片與相簿。

![瀏覽器指令碼中的 JavaScript，使用 Amazon S3 儲存貯體做為相簿。](http://docs.aws.amazon.com/zh_tw/sdk-for-javascript/v2/developer-guide/images/s3-photo-album-example.png)


瀏覽器指令碼使用適用於 JavaScript 的 SDK 與 Amazon S3 儲存貯體互動。使用下列 Amazon S3 用戶端類別的方法來啟用相簿應用程式：
+ [https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#listObjects-property](https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#listObjects-property)
+ [https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#headObject-property](https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#headObject-property)
+ [https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#putObject-property](https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#putObject-property)
+ [https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#upload-property](https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#upload-property)
+ [https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#deleteObject-property](https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#deleteObject-property)
+ [https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#deleteObjects-property](https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#deleteObjects-property)

## 先決條件任務
<a name="s3-example-photo-album-scenario-prerequisites"></a>

若要設定和執行此範例，您必須先完成這些任務：
+ 在 [Amazon S3 主控台](https://console.aws.amazon.com/s3/)中，建立您將用來將相片存放在相簿中的 Amazon S3 儲存貯體。如需在 主控台中建立儲存貯體的詳細資訊，請參閱《*Amazon Simple Storage Service 使用者指南*》中的[建立儲存貯體](https://docs.aws.amazon.com/AmazonS3/latest/userguide/create-bucket.html)。請確定您在**物件**上同時擁有**讀取**和**寫入**許可。如需設定儲存貯體許可的詳細資訊，請參閱[設定網站存取的許可](https://docs.aws.amazon.com/AmazonS3/latest/userguide/WebsiteAccessPermissionsReqd.html)。
+ 在 [Amazon Cognito 主控台](https://console.aws.amazon.com/cognito/)中，使用聯合身分建立 Amazon Cognito 身分集區，並在與 Amazon S3 儲存貯體相同的區域中為未驗證的使用者啟用存取。您必須在程式碼中包含身分集區 ID，來取得瀏覽器指令碼的登入資料。如需 Amazon Cognito 聯合身分的詳細資訊，請參閱《[Amazon Cognito 開發人員指南》中的 Amazon Cognito 身分集區 （聯合身分）](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-identity.html)。 *Amazon Cognito *
+ 在 [IAM 主控台](https://console.aws.amazon.com/iam/)中，尋找 Amazon Cognito 為未驗證使用者建立的 IAM 角色。新增下列政策，將讀取和寫入許可授予 Amazon S3 儲存貯體。如需建立 IAM 角色的詳細資訊，請參閱《*IAM 使用者指南*》中的[建立角色以將許可委派給 AWS 服務](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_create_for-service.html)。

  針對 Amazon Cognito 為未經驗證的使用者建立的 IAM 角色，使用此角色政策。
**警告**  
如果您為未經授權使用者啟用存取權，您將授與該儲存貯體以及儲存貯體中所有物件的寫入權限給全世界的所有人。在此範例中，此安全狀態非常有用，可讓您專注於範例的主要目標。不過，在許多實際情況下，強烈建議採用更嚴格的安全性 (例如使用經驗證的使用者和物件擁有權)。

------
#### [ JSON ]

****  

  ```
  {
     "Version":"2012-10-17",		 	 	 
     "Statement": [
        {
           "Effect": "Allow",
           "Action": [
              "s3:DeleteObject",
              "s3:GetObject",
              "s3:ListBucket",
              "s3:PutObject",
              "s3:PutObjectAcl"
           ],
           "Resource": [            
              "arn:aws:s3:::{{BUCKET_NAME}}",
              "arn:aws:s3:::{{BUCKET_NAME}}/*"
           ]
        }
     ]
  }
  ```

------

## 設定 CORS
<a name="s3-example-photo-album-cors-configuration"></a>

在瀏覽器指令碼可以存取 Amazon S3 儲存貯體之前，您必須先設定其 [CORS 組態](cors.md#configuring-cors-s3-bucket)，如下所示。

**重要**  
在新的 S3 主控台中，CORS 組態必須為 JSON 格式。

------
#### [ JSON ]

```
[
    {
        "AllowedHeaders": [
            "*"
        ],
        "AllowedMethods": [
            "HEAD",
            "GET",
            "PUT",
            "POST",
            "DELETE"
        ],
        "AllowedOrigins": [
            "*"
        ],
        "ExposeHeaders": [
            "ETag"
        ]
    }
]
```

------
#### [ XML ]

```
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
    <CORSRule>
        <AllowedOrigin>*</AllowedOrigin>
        <AllowedMethod>POST</AllowedMethod>
        <AllowedMethod>GET</AllowedMethod>
        <AllowedMethod>PUT</AllowedMethod>
        <AllowedMethod>DELETE</AllowedMethod>
        <AllowedMethod>HEAD</AllowedMethod>
        <AllowedHeader>*</AllowedHeader>
        <ExposeHeader>ETag</ExposeHeader>
    </CORSRule>
</CORSConfiguration>
```

------

## 網頁
<a name="s3-example-photo-album-html"></a>

上傳相片的應用程式 HTML 是由 <div> 元素所組成，該元素在建立上傳使用者界面之瀏覽器程式碼中。第一個 <script> 元素會新增軟體開發套件至瀏覽器指令碼。第二個 <script> 元素會新增存放瀏覽器指令碼的外部 JavaScript 檔案。

```
<!DOCTYPE html>
<html>
  <head>
     <!-- **DO THIS**: -->
    <!--   Replace SDK_VERSION_NUMBER with the current SDK version number -->
    <script src="https://sdk.amazonaws.com/js/aws-sdk-SDK_VERSION_NUMBER.js"></script>
    <script src="./s3_photoExample.js"></script>
    <script>
       function getHtml(template) {
          return template.join('\n');
       }
       listAlbums();
    </script>
  </head>
  <body>
    <h1>My Photo Albums App</h1>
    <div id="app"></div>
  </body>
</html>
```

## 設定軟體開發套件
<a name="s3-example-photo-album-configure-sdk"></a>

呼叫 `CognitoIdentityCredentials`方法並提供 Amazon Cognito 身分集區 ID，以取得設定 SDK 所需的登入資料。接下來，建立一個 `AWS.S3` 服務物件。

```
var albumBucketName = "BUCKET_NAME";
var bucketRegion = "REGION";
var IdentityPoolId = "IDENTITY_POOL_ID";

AWS.config.update({
  region: bucketRegion,
  credentials: new AWS.CognitoIdentityCredentials({
    IdentityPoolId: IdentityPoolId,
  }),
});

var s3 = new AWS.S3({
  apiVersion: "2006-03-01",
  params: { Bucket: albumBucketName },
});
```

此範例中幾乎所有其餘程式碼都組織為一系列的函數，這些函數收集並顯示有關儲存貯體中的相簿資訊，上傳和顯示上傳到相簿中的照片，並刪除照片和相簿。這些函數為：
+ `listAlbums`
+ `createAlbum`
+ `viewAlbum`
+ `addPhoto`
+ `deleteAlbum`
+ `deletePhoto`

## 於儲存貯體中列出相簿
<a name="s3-example-photo-album-list-albums"></a>

應用程式會在 Amazon S3 儲存貯體中建立相簿做為物件，其金鑰開頭為正斜線字元，表示物件功能為資料夾。若要在儲存貯體列出所有現有相簿，該應用程式的 `listAlbums` 函數會在使用 `commonPrefix` 時同時呼叫 `AWS.S3` 服務物件的 `listObjects` 方法，以便呼叫僅傳回做為相簿使用的物件。

函數的其餘部分會從 Amazon S3 儲存貯體取得相簿清單，並產生在網頁中顯示相簿清單所需的 HTML。它也會啟用刪除和開啟個別相簿。

```
function listAlbums() {
  s3.listObjects({ Delimiter: "/" }, function (err, data) {
    if (err) {
      return alert("There was an error listing your albums: " + err.message);
    } else {
      var albums = data.CommonPrefixes.map(function (commonPrefix) {
        var prefix = commonPrefix.Prefix;
        var albumName = decodeURIComponent(prefix.replace("/", ""));
        return getHtml([
          "<li>",
          "<span onclick=\"deleteAlbum('" + albumName + "')\">X</span>",
          "<span onclick=\"viewAlbum('" + albumName + "')\">",
          albumName,
          "</span>",
          "</li>",
        ]);
      });
      var message = albums.length
        ? getHtml([
            "<p>Click on an album name to view it.</p>",
            "<p>Click on the X to delete the album.</p>",
          ])
        : "<p>You do not have any albums. Please Create album.";
      var htmlTemplate = [
        "<h2>Albums</h2>",
        message,
        "<ul>",
        getHtml(albums),
        "</ul>",
        "<button onclick=\"createAlbum(prompt('Enter Album Name:'))\">",
        "Create New Album",
        "</button>",
      ];
      document.getElementById("app").innerHTML = getHtml(htmlTemplate);
    }
  });
}
```

## 在儲存貯體中建立相簿
<a name="s3-example-photo-album-create-album"></a>

若要在 Amazon S3 儲存貯體中建立相簿，應用程式的 `createAlbum` 函數會先驗證為新相簿指定的名稱，以確保其包含適當的字元。然後，函數會形成 Amazon S3 物件金鑰，並將其傳遞至 Amazon S3 服務物件的 `headObject`方法。此方法會回傳特定金鑰的中繼資料，因此，如果它回傳資料時，那麼具有該金鑰的物件就已經存在了。

如果相簿尚未存在，則函數會呼叫 `AWS.S3` 服務物件的 `putObject` 方法以建立該相簿。然後它將呼叫 `viewAlbum` 函數以顯示新的空相簿。

```
function createAlbum(albumName) {
  albumName = albumName.trim();
  if (!albumName) {
    return alert("Album names must contain at least one non-space character.");
  }
  if (albumName.indexOf("/") !== -1) {
    return alert("Album names cannot contain slashes.");
  }
  var albumKey = encodeURIComponent(albumName);
  s3.headObject({ Key: albumKey }, function (err, data) {
    if (!err) {
      return alert("Album already exists.");
    }
    if (err.code !== "NotFound") {
      return alert("There was an error creating your album: " + err.message);
    }
    s3.putObject({ Key: albumKey }, function (err, data) {
      if (err) {
        return alert("There was an error creating your album: " + err.message);
      }
      alert("Successfully created album.");
      viewAlbum(albumName);
    });
  });
}
```

## 檢視相簿
<a name="s3-example-photo-album-viewing-album"></a>

若要在 Amazon S3 儲存貯體中顯示相簿的內容，應用程式的 `viewAlbum` 函數會採用相簿名稱，並為該相簿建立 Amazon S3 金鑰。然後該函數會呼叫 `AWS.S3` 服務物件的 `listObjects` 方法以取得相簿中的所有物件 (相片) 清單。

其餘函數會從該相簿採用物件 (相片) 清單，並產生在網頁中顯示相片所需的 HTML。它也會啟用刪除個別照片並導覽回相簿清單的功能。

```
function viewAlbum(albumName) {
  var albumPhotosKey = encodeURIComponent(albumName) + "/";
  s3.listObjects({ Prefix: albumPhotosKey }, function (err, data) {
    if (err) {
      return alert("There was an error viewing your album: " + err.message);
    }
    // 'this' references the AWS.Response instance that represents the response
    var href = this.request.httpRequest.endpoint.href;
    var bucketUrl = href + albumBucketName + "/";

    var photos = data.Contents.map(function (photo) {
      var photoKey = photo.Key;
      var photoUrl = bucketUrl + encodeURIComponent(photoKey);
      return getHtml([
        "<span>",
        "<div>",
        '<img style="width:128px;height:128px;" src="' + photoUrl + '"/>',
        "</div>",
        "<div>",
        "<span onclick=\"deletePhoto('" +
          albumName +
          "','" +
          photoKey +
          "')\">",
        "X",
        "</span>",
        "<span>",
        photoKey.replace(albumPhotosKey, ""),
        "</span>",
        "</div>",
        "</span>",
      ]);
    });
    var message = photos.length
      ? "<p>Click on the X to delete the photo</p>"
      : "<p>You do not have any photos in this album. Please add photos.</p>";
    var htmlTemplate = [
      "<h2>",
      "Album: " + albumName,
      "</h2>",
      message,
      "<div>",
      getHtml(photos),
      "</div>",
      '<input id="photoupload" type="file" accept="image/*">',
      '<button id="addphoto" onclick="addPhoto(\'' + albumName + "')\">",
      "Add Photo",
      "</button>",
      '<button onclick="listAlbums()">',
      "Back To Albums",
      "</button>",
    ];
    document.getElementById("app").innerHTML = getHtml(htmlTemplate);
  });
}
```

## 新增相片至相簿
<a name="s3-example-photo-album-adding-photos"></a>

若要將相片上傳至 Amazon S3 儲存貯體中的相簿，應用程式的 `addPhoto` 函數會使用網頁中的檔案挑選器元素來識別要上傳的檔案。它接著會形成一個金鑰，以供現有相簿名稱和檔案名稱上傳相片。

函數會呼叫 Amazon S3 服務物件的 `upload`方法來上傳相片。在上傳相片後，該函數會重新顯示該相簿以顯示上傳的照片。

```
function addPhoto(albumName) {
  var files = document.getElementById("photoupload").files;
  if (!files.length) {
    return alert("Please choose a file to upload first.");
  }
  var file = files[0];
  var fileName = file.name;
  var albumPhotosKey = encodeURIComponent(albumName) + "/";

  var photoKey = albumPhotosKey + fileName;

  // Use S3 ManagedUpload class as it supports multipart uploads
  var upload = new AWS.S3.ManagedUpload({
    params: {
      Bucket: albumBucketName,
      Key: photoKey,
      Body: file,
    },
  });

  var promise = upload.promise();

  promise.then(
    function (data) {
      alert("Successfully uploaded photo.");
      viewAlbum(albumName);
    },
    function (err) {
      return alert("There was an error uploading your photo: ", err.message);
    }
  );
}
```

## 刪除相片
<a name="s3-example-photo-album-delete-photo"></a>

若要從 Amazon S3 儲存貯體中的相簿刪除相片，應用程式的 `deletePhoto` 函數會呼叫 Amazon S3 服務物件的 `deleteObject`方法。這會刪除由 `photoKey` 值傳遞給函數所指定的相片。

```
function deletePhoto(albumName, photoKey) {
  s3.deleteObject({ Key: photoKey }, function (err, data) {
    if (err) {
      return alert("There was an error deleting your photo: ", err.message);
    }
    alert("Successfully deleted photo.");
    viewAlbum(albumName);
  });
}
```

## 刪除相簿
<a name="s3-example-photo-album-delete-album"></a>

若要刪除 Amazon S3 儲存貯體中的相簿，應用程式的 `deleteAlbum` 函數會呼叫 Amazon S3 服務物件的 `deleteObjects`方法。

```
function deleteAlbum(albumName) {
  var albumKey = encodeURIComponent(albumName) + "/";
  s3.listObjects({ Prefix: albumKey }, function (err, data) {
    if (err) {
      return alert("There was an error deleting your album: ", err.message);
    }
    var objects = data.Contents.map(function (object) {
      return { Key: object.Key };
    });
    s3.deleteObjects(
      {
        Delete: { Objects: objects, Quiet: true },
      },
      function (err, data) {
        if (err) {
          return alert("There was an error deleting your album: ", err.message);
        }
        alert("Successfully deleted album.");
        listAlbums();
      }
    );
  });
}
```