我是 ReactJS 和 AWS 的新手。我想用一个简单的按钮创建一个简单的 ReactJS 前端,通过与 Lambda 函数集成的 API 网关将图像上传到 S3(lambda 函数为文件上传创建预签名的 url)。我遇到了 CORS 错误,我已经尝试了我在网上找到的所有内容,但似乎没有任何效果。我想要实现的主要目标是将图像上传到 S3 并获取图像的 url 以将其发布到 DynamoDB 表中作为参考。我不确定如何使所有这些组件一起工作。我关注了这篇文章:https ://blog.webiny.com/upload-files-to-aws-s3-using-pre-signed-post-data-and-a-lambda-function-7a9fb06d56c1
这是我的 Lambda 代码:
const S3 = require("aws-sdk/clients/s3");
const uniqid = require("uniqid");
const mime = require("mime");
/**
* Use AWS SDK to create pre-signed POST data.
* We also put a file size limit (100B - 10MB).
* @param key
* @param contentType
* @returns {Promise<object>}
*/
const createPresignedPost = ({ key, contentType }) => {
const s3 = new S3();
const params = {
Expires: 60,
Bucket: "uploadimage",
Conditions: [["content-length-range", 100, 3000000]], // 100Byte - 3MB
Fields: {
"Content-Type": contentType,
key
}
};
return new Promise(async (resolve, reject) => {
s3.createPresignedPost(params, (err, data) => {
if (err) {
reject(err);
return;
}
resolve(data);
});
});
};
/**
* We need to respond with adequate CORS headers.
* @type {{"Access-Control-Allow-Origin": string, "Access-Control-Allow-Credentials": boolean}}
*/
const headers = {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Credentials": true
};
module.exports.getPresignedPostData = async ({ body }) => {
try {
const { name } = JSON.parse(body);
const presignedPostData = await createPresignedPost({
key: `${uniqid()}_${name}`,
contentType: mime.getType(name)
});
return {
statusCode: 200,
headers,
body: JSON.stringify({
error: false,
data: presignedPostData,
message: null
})
};
} catch (e) {
return {
statusCode: 500,
headers,
body: JSON.stringify({
error: true,
data: null,
message: e.message
})
};
}
};
我创建了启用了 lambda 代理集成功能的 AWS API,以确保从此处传递标头以避免 CORS 错误,但它仍然以某种方式显示它们。
我的 ReactJS 前端组件代码如下所示(取自上面链接的教程):
import React from "react";
import Files from "react-butterfiles";
function Upload() {
/**
* Retrieve pre-signed POST data from a dedicated API endpoint.
* @param selectedFile
* @returns {Promise<any>}
*/
const getPresignedPostData = (selectedFile) => {
return new Promise((resolve) => {
const xhr = new XMLHttpRequest();
// Set the proper URL here.
const url = "https://xyz---.amazonaws.com/Upload/";
xhr.open("POST", url, true);
xhr.setRequestHeader("Content-Type", "application/json");
xhr.send(
JSON.stringify({
name: selectedFile.name,
type: selectedFile.type,
})
);
xhr.onload = function () {
resolve(JSON.parse(this.responseText));
};
});
};
/**
* Upload file to S3 with previously received pre-signed POST data.
* @param presignedPostData
* @param file
* @returns {Promise<any>}
*/
const uploadFileToS3 = (presignedPostData, file) => {
return new Promise((resolve, reject) => {
const formData = new FormData();
Object.keys(presignedPostData.fields).forEach((key) => {
formData.append(key, presignedPostData.fields[key]);
});
// Actual file has to be appended last.
formData.append("file", file);
const xhr = new XMLHttpRequest();
xhr.open("POST", presignedPostData.url, true);
xhr.send(formData);
xhr.onload = function () {
this.status === 204 ? resolve() : reject(this.responseText);
};
});
};
/**
* Component renders a simple "Select file..." button which opens a file browser.
* Once a valid file has been selected, the upload process will start.
* @returns {*}
* @constructor
*/
return (
<Files
onSuccess={async ([selectedFile]) => {
// Step 1 - get pre-signed POST data.
const { data: presignedPostData } = await getPresignedPostData(
selectedFile
);
// Step 2 - upload the file to S3.
try {
const { file } = selectedFile.src;
await uploadFileToS3(presignedPostData, file);
console.log("File was successfully uploaded!");
} catch (e) {
console.log("An error occurred!", e.message);
}
}}
>
{({ browseFiles }) => (
<button onClick={browseFiles}>Select file...</button>
)}
</Files>
);
}
export default Upload;
任何帮助将不胜感激!最终,我想将图像上传到 s3,然后将图像 url 存储在 dynamodb 表中作为参考。谢谢!