在 React Native Expo 应用程序中通过 aws-sdk-js-v3 上传文件

问题描述 投票:0回答:0

我有一个简单的 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
错误。只发生在安卓上。

react-native expo cloudflare aws-sdk-js
© www.soinside.com 2019 - 2024. All rights reserved.