从浏览器将照片上传到 Amazon S3 - Amazon SDK for JavaScript
Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅中国的 Amazon Web Services 服务入门

帮助我们改进Amazon SDK for JavaScript版本 3 (V3) 文档,方法是使用反馈链接,或者在上创建议题或拉取请求GitHub.

这些区域有:Amazon SDK for JavaScriptV3 API 参考指南详细描述了Amazon SDK for JavaScript版本 3 (V3)。

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

从浏览器将照片上传到 Amazon S3


                JavaScript code example that applies to browser execution

此浏览器脚本代码示例演示:

  • 如何创建允许用户在 Amazon S3 存储桶中创建相册并将照片上传到相册中的浏览器应用程序。

场景

在本示例中,一个简单的 HTML 页面提供了基于浏览器的应用程序,该应用程序在 Amazon S3 存储桶中创建相册,您可将照片上传到其中。通过该应用程序,您可以删除所添加的照片和相册。


                JavaScript在浏览器脚本中,它将 Amazon S3 存储桶用于存储相册。

浏览器脚本将 SDK 用于JavaScript与 Amazon S3 存储桶交互。使用 Amazon S3 客户端类的以下方法来启用相册应用程序:

前提任务

要设置和运行此示例,您必须先完成以下任务:

  • 设置项目环境以运行这些节点TypeScript示例,然后安装所需Amazon SDK for JavaScript和第三方模块。按照中的说明操作GitHub.

  • Amazon S3 控制台,创建 Amazon S3 存储桶,您将使用它将在相册中存储照片。有关在控制台中创建存储桶的更多信息,请参阅创建存储桶中的Amazon Simple Storage Service 用户指南. 确保您已拥有两个Read写入上的权限对象. 有关设置存储桶权限的更多信息,请参阅。设置访问网站的权限.

  • Amazon Cognito 控制台中,使用联合身份创建 Amazon Cognito 身份池,其中包含为与 Amazon S3 存储桶位于相同区域中的未验证身份用户启用的访问权限。您需要在代码中包含身份池 ID 以获取浏览器脚本的凭证。有关 Amazon Cognito 身份池的更多信息,请参阅Amazon Cognito 身份池(联合身份)中的Amazon Cognito 开发人员指南.

  • IAM 控制台,查找 Amazon Cognito 为未验证身份用户创建的 IAM 角色。添加以下策略,授予对 Amazon S3 存储桶的读取和写入权限。有关创建 IAM 角色的更多信息,请参阅创建向Amazon服务中的IAM 用户指南.

    为 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 配置如下所示。

重要

在 Amazon S3 中AmazonWeb 服务管理控制台,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>

安装所需的 SDK 客户端和软件包

安装以下 SDK 模块:

注意

有关安装 SDK 模块的信息,请参阅为 JavaScript 安装开发工具包.

  • 客户端-S3

  • 证书提供商

  • credential-provider-cognito-身份

安装 Webpack

要使用的 V3Amazon SDK for JavaScript在浏览器中,你需要 Webpack 来捆绑 JavaScript 模块和函数。

要安装 Web pack,请在命令行中运行以下命令:

npm install --save-dev webpack
重要

要查看此示例的 package.json 示例,请参阅Amazon SDK for JavaScript上的代码示例GitHub.

注意

有关安装 Webpack 的信息,请参阅使用 webpack 捆绑应用程序.

定义网页

照片查看应用程序的 HTML 包含<div>元素,浏览器脚本在其中创建查看/上传界面。

这些区域有:<script>元素添加<main.js>文件,其中包含所有必需的JavaScript例如。

注意

生成<main.js>文件,请参阅运行代码下面的。

注意

此示例导入并使用必需的Amazon服务 V3 包客户端、V3 命令,并使用send方法采用异步/等待模式。您可以使用 V2 命令创建此示例,而是通过进行一些小的更改。有关详细信息,请参阅 使用 V3 命令

<!DOCTYPE html> <html> <head> <script src="./main.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>

配置开发工具包

通过调用以获取配置开发工具包所需的凭证。CognitoIdentityCredentials方法,提供 Amazon Cognito 身份池 ID。接下来,创建一个S3客户端服务对象。

注意

此示例导入并使用必需的Amazon服务 V3 包客户端、V3 命令,并使用send方法采用异步/等待模式。您可以使用 V2 命令创建此示例,而是通过进行一些小的更改。有关详细信息,请参阅 使用 V3 命令

// Load the required clients and packages const { CognitoIdentityClient } = require("@aws-sdk/client-cognito-identity"); const { fromCognitoIdentityPool, } = require("@aws-sdk/credential-provider-cognito-identity"); const { S3Client, PutObjectCommand, ListObjectsCommand, DeleteObjectCommand, DeleteObjectsCommand } = require("@aws-sdk/client-s3"); // Set the AWS Region const REGION = "REGION"; //REGION // Initialize the Amazon Cognito credentials provider const s3 = new S3Client({ region: REGION, credentials: fromCognitoIdentityPool({ client: new CognitoIdentityClient({ region: REGION }), identityPoolId: "IDENTITY_POOL_ID", // IDENTITY_POOL_ID }), }); const albumBucketName = "BUCKET_NAME"; //BUCKET_NAME

此示例中几乎所有剩余的代码组织成一系列函数,这些函数收集并提供存储桶中相册的相关信息,上传并显示上传到相册中的照片,以及删除照片和相册。这些函数包括:

  • listAlbums

  • createAlbum

  • viewAlbum

  • addPhoto

  • deleteAlbum

  • deletePhoto

在存储桶中列出相册

应用程序在 Amazon S3 存储桶中将相册创建为对象,其键以正斜杠字符开头,指示该对象用作文件夹。为列出存储桶中的所有现有相册,应用程序的listAlbums函数调用ListObjectsCommand的方法S3使用时的客户端服务对象commonPrefix所以调用只返回用作相册的对象。

函数的剩余部分从 Amazon S3 存储桶获取相册列表,并生成在网页中显示相册列表所需的 HTML。它还支持删除和打开单独的相册。

注意

此示例导入并使用必需的Amazon服务 V3 包客户端、V3 命令,并使用send方法采用异步/等待模式。您可以使用 V2 命令创建此示例,而是通过进行一些小的更改。有关详细信息,请参阅 使用 V3 命令

// A utility function to create HTML function getHtml(template) { return template.join("\n"); } // Make getHTML function available to the browser window.getHTML = getHtml; // List the photo albums that exist in the bucket const listAlbums = async () => { try { const data = await s3.send( new ListObjectsCommand({ Delimiter: "/", Bucket: albumBucketName }) ); if (data.CommonPrefixes === undefined) { const htmlTemplate = [ "<p>You don't have any albums. You need to create an album.</p>", "<button onclick=\"createAlbum(prompt('Enter album name:'))\">", "Create new album", "</button>", ]; document.getElementById("app").innerHTML = htmlTemplate; } 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 an album name to view it.</p>", "<p>Click the X to delete the album.</p>", ]) : "<p>You do not have any albums. You need to create an album."; const 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); } } catch (err) { return alert("There was an error listing your albums: " + err.message); } }; // Make listAlbums function available to the browser window.listAlbums = listAlbums;

在存储桶中创建相册

为在 Amazon S3 存储桶中创建相册,应用程序的createAlbum函数首先验证为新相册提供的名称,确保它包含合适的字符。然后,函数构成 Amazon S3 对象键,将其传递到headObjectAmazon S3 服务对象的方法。此方法返回指定键的元数据,因此如果它返回数据,则具有该键的对象已存在。

如果相册尚不存在,则函数调用PutObjectCommand的方法S3用于创建相册的客户端服务对象。然后,它调用 viewAlbum 函数以显示新的空相册。

注意

此示例导入并使用必需的Amazon服务 V3 包客户端、V3 命令,并使用send方法采用异步/等待模式。您可以使用 V2 命令创建此示例,而是通过进行一些小的更改。有关详细信息,请参阅 使用 V3 命令

// Create an album in the bucket const createAlbum = async (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); try { const key = albumKey + "/"; const params = { Bucket: albumBucketName, Key: key }; const data = await s3.send(new PutObjectCommand(params)); alert("Successfully created album."); viewAlbum(albumName); } catch (err) { return alert("There was an error creating your album: " + err.message); } }; // Make createAlbum function available to the browser window.createAlbum = createAlbum;

查看相册

为显示 Amazon S3 存储桶中相册的内容,应用程序的viewAlbum函数获取相册名称并为该相册创建 Amazon S3 密钥。然后该函数调用listObjects的方法S3客户端服务对象,获取相册中所有对象(照片)的列表。

函数的剩余部分从相册获取对象(照片)列表并生成在网页中显示照片所需的 HTML。它还支持删除单独的照片以及导航回相册列表。

// View the contents of an album const viewAlbum = async (albumName) => { const albumPhotosKey = encodeURIComponent(albumName) + "/"; try { const data = await s3.send( new ListObjectsCommand({ Prefix: albumPhotosKey, Bucket: albumBucketName, }) ); if (data.Contents.length === 1) { var htmlTemplate = [ "<p>You don't have any photos in this album. You need to add photos.</p>", '<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); } else { console.log(data); const href = "https://s3." + REGION + ".amazonaws.com/"; const bucketUrl = href + albumBucketName + "/"; const photos = data.Contents.map(function (photo) { const photoKey = photo.Key; console.log(photo.Key); const 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 the X to delete the photo.</p>" : "<p>You don't have any photos in this album. You need to add photos.</p>"; const 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); document.getElementsByTagName("img")[0].remove(); } } catch (err) { return alert("There was an error viewing your album: " + err.message); } }; // Make viewAlbum function available to the browser window.viewAlbum = viewAlbum;

将照片添加到相册

为将照片上传到 Amazon S3 存储桶中的相册,应用程序的addPhoto函数在网页中使用文件选取器元素来标识要上传的文件。然后,它从当前相册名称和文件名,为上传的照片构成一个键。

函数调用putObject用于上传照片的 Amazon S3 服务对象的方法。上传照片后,函数将重新显示相册,这样上传的照片会显示。

// Add a photo to an album const addPhoto = async (albumName) => { const files = document.getElementById("photoupload").files; try { const albumPhotosKey = encodeURIComponent(albumName) + "/"; const data = await s3.send( new ListObjectsCommand({ Prefix: albumPhotosKey, Bucket: albumBucketName }) ); const file = files[0]; const fileName = file.name; const photoKey = albumPhotosKey + fileName; const uploadParams = { Bucket: albumBucketName, Key: photoKey, Body: file }; try { const data = await s3.send(new PutObjectCommand(uploadParams)); alert("Successfully uploaded photo."); viewAlbum(albumName); } catch (err) { return alert("There was an error uploading your photo: ", err.message); } } catch (err) { if (!files.length) { return alert("Choose a file to upload first."); } } }; // Make addPhoto function available to the browser window.addPhoto = addPhoto;

删除照片

为从 Amazon S3 存储桶中删除相册中的照片,应用程序的deletePhoto函数调用DeleteObjectCommandAmazon S3 客户端服务对象的方法。这会删除传递到函数的 photoKey 值指定的照片。

// Delete a photo from an album const deletePhoto = async (albumName, photoKey) => { try { console.log(photoKey); const params = { Key: photoKey, Bucket: albumBucketName }; const data = await s3.send(new DeleteObjectCommand(params)); console.log("Successfully deleted photo."); viewAlbum(albumName); } catch (err) { return alert("There was an error deleting your photo: ", err.message); } }; // Make deletePhoto function available to the browser window.deletePhoto = deletePhoto;

删除相册

为从 Amazon S3 存储桶中删除相册,应用程序的deleteAlbum函数调用deleteObjectsAmazon S3 客户端服务对象的方法。

// Delete an album from the bucket const deleteAlbum = async (albumName) => { const albumKey = encodeURIComponent(albumName) + "/"; try { const params = { Bucket: albumBucketName, Prefix: albumKey }; const data = await s3.send(new ListObjectsCommand(params)); const objects = data.Contents.map(function (object) { return { Key: object.Key }; }); try { const params = { Bucket: albumBucketName, Delete: { Objects: objects }, Quiet: true, }; const data = await s3.send(new DeleteObjectsCommand(params)); listAlbums(); return alert("Successfully deleted album."); } catch (err) { return alert("There was an error deleting your album: ", err.message); } } catch (err) { return alert("There was an error deleting your album1: ", err.message); } }; // Make deleteAlbum function available to the browser window.deleteAlbum = deleteAlbum;

运行代码

为此示例运行代码

  1. 将所有代码保存为s3_PhotoExample.js.

    注意

    此文件可用此处GitHub.

  2. Replace“地区”和你的Amazon区域,例如 “us-east-1”。

  3. Replace“BUCKET_NAME”与 Amazon S3 存储桶一起使用。

  4. Replace“身份 _POOL_ID”使用IdentityPool我来自示例页面为本示例创建的 Amazon Cognito 身份池。

    注意

    这些区域有:IDENTITY_POOL_ID在控制台中显示为红色。

  5. 在命令行中运行以下命令以捆绑JavaScript对于此示例,请参阅一个名为的文件<main.js>

    npx webpack ./src/s3_PhotoExample.js --mode development --target web --no-devtool -o main.js
    注意

    有关安装的信息WebPack,请参阅使用 webpack 捆绑应用程序.

在命令行中运行以下命令:

node s3_PhotoExample.js