我正在使用 Expo 和 AWS Amplify 将我的 React Native 应用程序从版本 5 迁移到版本 6。我在尝试使用 uploadData 方法将文件上传到 S3 时遇到 AccessDenied:访问被拒绝错误。
这是我的版本 5 的代码,运行良好:
import * as ImageManipulator from 'expo-image-manipulator';
import { Storage } from 'aws-amplify';
import uuid from 'react-native-uuid';
export async function uploadImage(uri: string): Promise<string | null> {
try {
if (!uri) {
throw new Error('Invalid URI provided for uploading the image');
}
const id = uuid.v4().toString(); // Generate a version 4 UUID
const response = await fetch(uri);
if (!response.ok && response.type !== 'default') {
throw new Error(`HTTP error! status: ${response.status}`);
}
const blob = await response.blob();
if (!blob) {
throw new Error('Failed to convert the response to a blob');
}
const result = await Storage.put(id, blob);
if (!result.key) {
throw new Error('Failed to upload the image');
}
return result.key;
} catch (err) {
console.error('Error uploading file: ', err);
return null;
}
}
这是我的版本 6 的代码,它给出了 AccessDenied 错误:
import { getUrl, uploadData } from 'aws-amplify/storage';
export async function uploadImage(uri: string): Promise<string | null> {
try {
if (!uri) {
throw new Error('Invalid URI provided for uploading the image');
}
const id = uuid.v4().toString(); // Generate a version 4 UUID
const response = await fetch(uri);
if (!response.ok && response.type !== 'default') {
throw new Error(`HTTP error! status: ${response.status}`);
}
const blob = await response.blob();
if (!blob) {
throw new Error('Failed to convert the response to a blob');
}
console.log('id', id);
console.log('blob', blob);
const operation = uploadData({ path: id, data: blob })
const result = await operation.result
console.log('result', result);
if (!result.path) {
throw new Error('Failed to upload the image');
}
return result.path;
} catch (err) {
console.error('Error uploading file: ', err);
return null;
}
}
错误信息是:
Error uploading file: [AccessDenied: Access Denied]
据我了解,该问题可能与 uploadData 中使用的路径有关。我应该如何正确指定路径或设置访问级别来修复此错误?
从 Amplify v5 迁移到 v6 时,S3 上传的路径和访问级别的管理方式发生了一些变化。在 v6 中,您需要在路径中显式指定访问级别。
这是 v6 的更正代码:
import { uploadData } from 'aws-amplify/storage';
import uuid from 'react-native-uuid';
export async function uploadImage(uri: string): Promise<string | null> {
try {
if (!uri) {
throw new Error('Invalid URI provided for uploading the image');
}
const id = uuid.v4().toString(); // Generate a version 4 UUID
const response = await fetch(uri);
if (!response.ok && response.type !== 'default') {
throw new Error(`HTTP error! status: ${response.status}`);
}
const blob = await response.blob();
if (!blob) {
throw new Error('Failed to convert the response to a blob');
}
console.log('id', id);
console.log('blob', blob);
const operation = uploadData({ path: `public/${id}`, data: blob }) // Specify the public access level in the path
const result = await operation.result
console.log('result', result);
if (!result.path) {
throw new Error('Failed to upload the image');
}
return result.path;
} catch (err) {
console.error('Error uploading file: ', err);
return null;
}
}
说明: 路径中的访问级别: 在 v6 中,您需要在 uploadData 方法的路径中指定访问级别。默认情况下,访问级别设置为 public,但您需要将其显式包含在路径中,例如 public/{id}。
文档参考: 根据 Amplify 文档,路径必须包含访问级别前缀:
公开:您的应用程序的所有用户都可以访问。文件存储在 S3 存储桶中的 public/ 路径下。 受保护:所有用户均可读取,但仅创建用户可写入。文件存储在 protected/{user_identity_id}/ 下。 私有:仅供个人用户访问。文件存储在 private/{user_identity_id}/ 下。 参考资料:
此更改应该可以解决您遇到的 AccessDenied 错误。如果您还有其他问题,请确保正确配置您的 IAM 策略和 S3 存储桶策略以允许必要的权限。