從瀏覽器將照片上傳到 Amazon S3 - AWS SDK for JavaScript

我們宣布即將推出 end-of-support AWS SDK for JavaScript v2。建議您遷移至 AWS SDK for JavaScript v3。如需日期、其他詳細資訊和如何遷移的資訊,請參閱連結公告。

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

從瀏覽器將照片上傳到 Amazon S3

JavaScript code example that applies to browser execution

此瀏覽器程式碼範例顯示:

  • 如何創建允許用戶在 Amazon S3 存儲桶中創建相冊並將照片上傳到相冊的瀏覽器應用程序。

使用案例

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

JavaScript 在使用 Amazon S3 存儲桶相冊的瀏覽器腳本中。

瀏覽器指令碼使用開發 JavaScript 套件與 Amazon S3 儲存貯體進行互動。使用下列 Amazon S3 用戶端類別的方法來啟用相簿應用程式:

先決條件任務

若要設定和執行此範例,您必須先完成這些任務:

  • Amazon S3 主控台中,建立一個 Amazon S3 儲存貯體,您將用來將相片存放在相簿中。如需在主控台中建立值區的詳細資訊,請參閱 Amazon 簡單儲存服務使用者指南中的建立儲存貯體。請確定您同時擁有物件讀取寫入權限。如需有關設定值區權限的詳細資訊,請參閱設定網站存取權限

  • Amazon Cognito 主控台中,使用聯合身分建立 Amazon Cognito 身分集區,並為與 Amazon S3 儲存貯體位於相同區域中的未驗證使用者啟用存取權限。您必須在程式碼中包含身分集區 ID,來取得瀏覽器指令碼的登入資料。如需 Amazon Cognito 聯合身分識別的詳細資訊,請參閱 Amazon Cognito 開發人員指南中的 Amazon Cognito 身分識別集區 (聯合身分識別)

  • IAM 主控台中,尋找 Amazon Cognito 為未經驗證的使用者建立的 IAM 角色。新增下列政策以授與讀取和寫入權限給 Amazon S3 儲存貯體。如需有關建立 IAM 角色的詳細資訊,請參閱 IAM 使用者指南中的建立角色以將許可委派給AWS服務

    針對 Amazon Cognito 為未經驗證的使用者建立的 IAM 角色使用此角色政策。

    警告

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

    { "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

在瀏覽器指令碼可以存取 Amazon S3 儲存貯體之前,您必須先設定其 CORS 組態,如下所示。

重要

在新的 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>

網頁

上傳相片的應用程式 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>

設定軟體開發套件

透過呼叫提供 Amazon Cognito 身分識別集區識別碼的CognitoIdentityCredentials方法來取得設定 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

於儲存貯體中列出相簿

應用程式會在 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); } }); }

在儲存貯體中建立相簿

若要在 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); }); }); }

檢視相簿

若要在 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); }); }

新增相片至相簿

若要將相片上傳到 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); } ); }

刪除相片

若要從 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); }); }

刪除相簿

若要刪除 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(); } ); }); }