如何使用expo图像选择器将简单图像从移动设备上传到AWS S3?

时间:2017-12-01 19:05:18

标签: react-native amazon-s3 expo

我使用本地化的反应世界,我真的坚持这个...世博会不支持我多年来上传我的图像使用的firebase云存储。所以我留下了我从未使用过的AWS S3。我已经在github上找到了这个例子:https://github.com/expo/image-upload-example/ 但我无法掌握后端部分是什么以及使用的apiURl是什么......我道歉我没有提供任何代码尝试但是我完全失去了我可以'在AWS上真正看到了大量的bla bla bla文档。

我已在AWS S3控制台中创建它,以便公开访问我创建的存储桶。我没有问题。我不需要用户上传图像以及任何其他限制只需要完成简单的上传。

所以,如果有人可以帮助我完成这个代码。提前致谢。

2 个答案:

答案 0 :(得分:0)

我没有专门使用过Expo,但我已经设置了我的RN项目,可以上传到s3。鉴于您发布的示例,它与我最终做的非常相似。

显然,您需要做的第一件事就是在AWS S3上设置一个存储桶。在AWS控制台中,您应该能够找到特定的访问密钥和访问密钥,您将需要这两者以及您的存储桶名称。

您发布的示例背后的想法,以及我最终做的是拥有一个受控服务器,您可以安全地使用访问密钥和机密创建一个独特的“签名”网址,可用于直接上传图像进入你的水桶。您不希望在您的客户端上执行此操作b / c在您的客户端上有一个秘密只是要求被黑客入侵。假设客户端上的任何内容都不是完全安全的。

我已经在构建一个节点服务器作为我的应用程序的后端,所以我已经启动并运行了这部分。如果您不熟悉创建后端服务器,我建议您查找如何设置Express服务器here。您可以在heroku等服务上免费托管应用程序(有限制)。甚至有一篇很好的文章更详细地介绍了整个过程here。基本上,您创建的应用程序具有可由您的客户端应用程序点击的独特GET路径。该路由将接受一个查询参数,其中包含要上载的文件的文件名。您应该使用official aws sdk来获取您的访问密钥,密码,存储桶名称和文件名,然后生成一个唯一的网址,然后将其发送回您的客户端应用。

基本上你的客户端应用程序将做的是准备需要上传的文件。您应该准备好文件的文件名,然后将GET请求发送到您刚在Express应用上设置的网址路由。当您从服务器收到回复时,它应该包含该唯一网址。然后,我使用react native fetch blob库对您刚收到的唯一网址执行PUT请求。如果一切顺利,应该将文件直接上传到该存储桶。确保将标题中的Content-Type设置为您要上传的文件类型。

我知道这不是一堆可以上传的代码,但它应该可以帮助您了解所需的内容并让您朝着正确的方向前进。

答案 1 :(得分:0)

我遇到同样的问题很长时间了。这就是我所做的。

请确保按照放大指南设置应用。 amplify initamplify add authamplify push,然后是 amplify add storage,然后执行此操作。

import Amplify, { Storage } from 'aws-amplify'
import config from './src/aws-exports'
// import awsconfig from './aws-exports';
// Might need to switch line 7 to awsconfig 
Amplify.configure(config)

import { StatusBar } from 'expo-status-bar';
import React, { useState, useEffect } from 'react';
import { Button, Image, View, Platform, StyleSheet, Text, TextInput } from 'react-native';
import * as ImagePicker from 'expo-image-picker';

function App() {
  const [image, setImage] = useState(null)
  const [name, setName] = useState('Evan Erickson')

  useEffect(() => {
    (async () => {
      if (Platform.OS !== 'web') {
        const { status } = await ImagePicker.requestMediaLibraryPermissionsAsync();
        if (status !== 'granted') {
          alert('Sorry, we need camera roll permissions to make this work!');
        }
      }
    })();
  }, []);

  const pickImage = async () => {
    let result = await ImagePicker.launchImageLibraryAsync({
      mediaTypes: ImagePicker.MediaTypeOptions.All,
      allowsEditing: true,
      aspect: [4, 3],
      quality: 1,
    });
    
    console.log(result) 

    async function pathToImageFile(data) {
      try {
        const response = await fetch(data);
        const blob = await response.blob();
        await Storage.put(`customers/${name}`, blob, {
          contentType: 'image/jpeg', // contentType is optional
        });
      } catch (err) {
        console.log('Error uploading file:', err);
      }
    }
    // later
    pathToImageFile(result.uri);
  }

  return (
    <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
      <Button title="Pick an image from camera roll" onPress={pickImage} />
      {image && <Image source={{ uri: image }} style={{ width: 200, height: 200 }} />}
      <Button title="Upload image" onPress={() => {alert(image)}} />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
  },
});

export default withAuthenticator(App)```