我有一个简单的 React Native Expo 应用程序。有一个按钮可以打开 expo-image-picker。从那里,图像被 expo-image-manipulator 压缩。之后我想使用 aws-sdk-js-v3 将图像上传到 Cloudflare R2。但是,我无法让上传工作。上传失败并显示消息:Typeerror: undefined is not a function。如何修复上传?
import { StatusBar } from "expo-status-bar";
import { StyleSheet, Text, View, Pressable } from "react-native";
import {
S3Client,
PutObjectCommand,
} from "@aws-sdk/client-s3";
import { ACCESS_KEY, SECRET_ACCESS_KEY, ACCOUNT_ID } from "@env";
import * as ImagePicker from "expo-image-picker";
import * as FileSystem from "expo-file-system";
import * as ImageManipulator from "expo-image-manipulator";
import "react-native-url-polyfill/auto";
import "react-native-get-random-values";
import { Buffer } from "buffer";
export default function App() {
const s3Client = new S3Client({
region: "auto",
endpoint: `https://${ACCOUNT_ID}.r2.cloudflarestorage.com`,
credentials: {
accessKeyId: ACCESS_KEY,
secretAccessKey: SECRET_ACCESS_KEY,
},
});
const compressSizer = (size) => {
const MB = size / Math.pow(1024, 2);
if (MB < 0.5) return 1;
return 0.5 / MB;
};
const getFileSize = async (fileURI) => {
const fileInfo = await FileSystem.getInfoAsync(fileURI);
if (!fileInfo.exists) {
throw new Error("File does not exist");
}
return fileInfo.size;
};
const pickImage = async () => {
const result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ImagePicker.MediaTypeOptions.Images,
allowsEditing: true,
aspect: [4, 4],
quality: 1,
});
if (!result.canceled) {
const size = await getFileSize(result.assets[0].uri);
console.info("FileSize", size);
const compress = compressSizer(size);
const compressedPhoto = await ImageManipulator.manipulateAsync(
result.assets[0].uri,
[],
{
base64: true,
compress,
format: ImageManipulator.SaveFormat.JPEG,
}
);
const fileSize2 = await getFileSize(compressedPhoto.uri);
console.info("CompressedSize", fileSize2);
return compressedPhoto;
}
return;
};
const postImage = async () => {
try {
const file = await pickImage();
const uint8Array = Buffer.from(file.base64, "base64");
const filename = Math.random() * 100000;
const input = {
Bucket: "bucket",
Key: filename,
Body: uint8Array,
};
const command = new PutObjectCommand(input);
const s3response = await s3Client.send(command);
console.log(s3response);
} catch (e) {
console.log(e);
}
};
return (
<View style={styles.container}>
<Pressable
onPress={() => postImage()}
style={{ height: 50, backgroundColor: "#ebebeb" }}
>
<Text>Upload image</Text>
</Pressable>
<StatusBar style="auto" />
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#fff",
alignItems: "center",
justifyContent: "center",
},
});
我也尝试过使用其他方法。 带缓冲器:
const fileData = await FileSystem.readAsStringAsync(localUri, {
encoding: FileSystem.EncodingType.Base64,
});
const buffer = Buffer.from(fileData, "base64");
const input = {
Body: buffer,
Bucket: "bucket",
Key: filename,
};
有斑点:
const response = await fetch(fileUri);
const blob = await response.blob();
const input = {
Bucket: "bucket",
Key: filename,
Body: blob,
};
非常感谢任何帮助。
编辑:经过进一步观察,上面的一些选项起作用了。但是只有在第一次上传时,之后才会抛出
undefined is not a function
错误。只发生在安卓上。