无法通过 Expo 和 AWS SDK 将图像上传到 Digital Ocean 空间

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

我尝试使用 Expo Image Picker 和 AWS SDK 将图像上传到我的 DigitalOcean Spaces,但我不断遇到此错误:

ERROR  Error uploading image: [TypeError: Network request failed]

这是我用来上传图像的相关代码:

import AsyncStorage from '@react-native-async-storage/async-storage';
import axios from 'axios';
import * as ImagePicker from 'expo-image-picker';
import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3';
import 'react-native-get-random-values'; // This polyfills crypto.getRandomValues
import { v4 as uuidv4 } from 'uuid';
import { spaces } from '../config/digitalOcean';
import 'react-native-url-polyfill/auto';
import { ReadableStream } from 'web-streams-polyfill';
globalThis.ReadableStream = ReadableStream;

export default function AddItems({ navigation }) {
  const [produceName, setProduceName] = useState('');
  const [quantity, setQuantity] = useState('');
  const [price, setPrice] = useState('');
  const [itemImage, setItemImage] = useState('');
  const [phoneNumber, setPhoneNumber] = useState('');
  const [uploading, setUploading] = useState(false);

  const s3Client = new S3Client({
    endpoint: spaces.url,
    forcePathStyle: false,
    region: "blr1",
    credentials: {
      accessKeyId: spaces.spacesKey,
      secretAccessKey: spaces.spacesSecret
    }
  });

  useEffect(() => {
    const loadPhoneNumber = async () => {
      try {
        const storedPhoneNumber = await AsyncStorage.getItem('phone');
        if (storedPhoneNumber) {
          setPhoneNumber(storedPhoneNumber);
        } else {
          Alert.alert('Error', 'Phone number not found');
        }
      } catch (error) {
        console.error('Error loading phone number from AsyncStorage:', error);
      }
    };

    loadPhoneNumber();
  }, []);

  const pickImageAsync = async () => {
    let result = await ImagePicker.launchImageLibraryAsync({
      allowsEditing: true,
      quality: 1,
    });

    if (!result.canceled) {
      uploadImage(result.assets[0]);
    } else {
      alert('You did not select any image.');
    }
  };

  const getImageBlob = (uri) => {
    return new Promise((resolve, reject) => {
      const xhr = new XMLHttpRequest();
      xhr.onload = function() {
        resolve(xhr.response);
      };
      xhr.onerror = function() {
        reject(new Error('XMLHttpRequest failed'));
      };
      xhr.responseType = 'blob';
      xhr.open('GET', uri, true);
      xhr.send(null);
    });
  };

  const uploadImage = async (imageAsset) => {
    setUploading(true);
    const fileName = `${uuidv4()}.jpg`;

    try {
      const response = await fetch(imageAsset.uri);
      const blob = await getImageBlob(imageAsset.uri);
      console.log("these happened without error");
      console.log(response);
      console.log(blob);

      const params = {
        Bucket: spaces.name,
        Key: fileName,
        Body: blob,
        ACL: "public-read",
        ContentType: 'multipart/form-data',
      };

      const data = await s3Client.send(new PutObjectCommand(params));
      console.log(data);

      const imageUrl = spaces.url + "/" + fileName;
      setItemImage(imageUrl);
      Alert.alert('Success', 'Image uploaded successfully');
    } catch (error) {
      console.error('Error uploading image:', error);
      Alert.alert('Error', 'Failed to upload image');
    }
    setUploading(false);
  };

  const handleSubmit = async () => {
    if (!produceName || !quantity || !price) {
      Alert.alert('Error', 'All fields are required');
      return;
    }

    try {
      const formData = {
        phoneNumber,
        itemName: produceName,
        quantity,
        price,
        itemImage,
      };

      const response = await axios.post(
        'myurl/api/supplier/add-item',
        formData
      );

      if (response.status === 200) {
        Alert.alert('Success', 'Item added successfully!');
        navigation.goBack();
      }
    } catch (error) {
      console.error('Error adding item:', error.response?.data || error.message);
      Alert.alert(
        'Error',
        error.response?.data?.message || 'Failed to add item, please try again'
      );
    }
  };

我已尝试以下方法,但尚未找到解决方案:

  1. 确保我拥有 DigitalOcean Spaces 的有效凭证。
  2. 仔细检查spaces.url、accessKeyId和secretAccessKey以确保它们正确。

尝试上传图像时出现网络请求失败错误的原因可能是什么?我处理图像 blob 或 AWS S3 配置的方式有问题吗?

react-native expo digital-ocean digital-ocean-spaces
1个回答
0
投票

尝试使用 fetch 创建像这样的 blob,并确保 DigitalOcean 空间上的 cors 策略已包含在 AllowedMethods 中放置和发布。

const getImageBlob = async (uri) => {
  const response = await fetch(uri);
  const blob = await response.blob();
  return blob;
};
最新问题
© www.soinside.com 2019 - 2025. All rights reserved.