Вам не нужны и Cloudinary, и Amazon S3, мы просто рассматриваем оба варианта 😄

Загрузка изображения или видео с нашего телефона в приложение - обычная практика. React Native и Expo делают процесс получения документа и его отправки в серверную часть довольно приятным. На вашем сервере вы захотите хранить эти активы в безопасном облачном хранилище. Cloudinary и Amazon S3 предлагают бесплатные пробные версии объемом более 5 ГБ.

Внешний интерфейс

Expo - это бесплатный набор инструментов с открытым исходным кодом, созданный на основе React Native, который поможет вам создавать собственные проекты для iOS и Android с использованием JavaScript и React.
Они упрощают весь процесс разработки приложения и его публикации. У вас также будет доступ к Expo SDK, библиотеке, которая предоставляет широкий спектр нативных API для iOS и Android, таких как Camera API.

Expo дает нам доступ к DocumentPicker и ImagePicker, чтобы забрать документ или изображение с нашего телефона. Код с React Native будет следующим для нашего компонента «PickImageorDocument». Изображение - это документ, само собой разумеется, но это только для того, чтобы показать оба варианта.

«PickDocument» извлекает документ из нашего телефона, а «pickImage» получает изображение из нашего телефона. Мы устанавливаем локальное состояние нашего компонента с помощью uri ресурса.

import React from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { StyleSheet, Image, View } from 'react-native';
import { DocumentPicker, ImagePicker } from 'expo';
import { Button, Text, Header } from 'react-native-elements';
import { SERVER_URI, PostFunStuff } from '../../constant';
class FunPost extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      image: null,
    };
    this.postFunStuff = this.postFunStuff.bind(this);
    this.pickDocument = this.pickDocument.bind(this);
    this.pickImage = this.pickImage.bind(this);
    this.postPic = this.postPic.bind(this);
  }
pickDocument = async () => {
    const result = await DocumentPicker.getDocumentAsync({});
    console.log('result', result);
    if (!result.cancelled) {
      this.setState({
        image: result,
      });
    }
  }
pickImage = async () => {
    const result = await ImagePicker.launchImageLibraryAsync({
      allowsEditing: true,
      base64: true,
    });
if (!result.cancelled) {
      this.setState({
        image: result.uri,
      });
    }
  };

Затем нам нужно отправить этот актив на наш сервер.

Самый распространенный способ отправить документ по http - с помощью formData. Определение MDN следующее:

Интерфейс FormData предоставляет способ легко создать набор пар ключ / значение, представляющих поля формы и их значения, которые затем можно легко отправить с помощью метода XMLHttpRequest.send(). Он использует тот же формат, что и форма, если бы тип кодировки был установлен на "multipart/form-data".

Давайте напишем функцию для отправки нашего документа и функцию для отправки изображения, чтобы увидеть узор. Мы добавляем ключ «photo» в первую функцию и ключ «документ» во вторую функцию в fromData. Мы передаем местоположение файла, тип файла (png, mp4…) и имя файла.

postPicture() {
const apiUrl = `${SERVER_URI}/upload`;
const uri = this.state.image;
const uriParts = uri.split('.');
const fileType = uriParts[uriParts.length - 1];
const formData = new FormData();
    formData.append('photo', {
      uri,
      name: `photo.${fileType}`,
      type: `image/${fileType}`,
    });
const options = {
      method: 'POST',
      body: formData,
      headers: {
        Accept: 'application/json',
        'Content-Type': 'multipart/form-data',
      },
    };
return fetch(apiUrl, options);
  }
postDocument() {
 const apiUrl = `${SERVER_URI}/upload`;
 const { name, uri } = this.state.image;
 const uriParts = name.split('.');
 const fileType = uriParts[uriParts.length - 1];
const formData = new FormData();
    formData.append('document', {
      uri,
      name,
      type: `application/${fileType}`,
    });
const options = {
      method: 'POST',
      body: formData,
      headers: {
        Accept: 'application/json',
        'Content-Type': 'multipart/form-data',
      },
    };
return fetch(apiUrl, options);
  }

Бэкэнд

На внутреннем уровне нам нужно импортировать Multer, промежуточное программное обеспечение node.js для обработки multipart/form-data, которое в основном используется для загрузки файлов.

app.post('/upload/, (res, req) => {
console.log(req.files)
});
req.files is an object with the document or picture key and the following:
{ document:
   { name: 'IMG_7353.JPG',
     data: <Buffer ff d8 ff e1 0f fe 45 78 69 66 00 00 4d 4d 00 2a 00 00 00 08 00 0b 01 0f 00 02 00 00 00 06 00 00 00 92 01 10 00 02 00 00 00 0a 00 00 00 98 01 12 00 03 ... >,
     encoding: '7bit',
     mimetype: 'application/jpg',
     mv: [Function: mv] } }

req.files имел имя, данные (необработанный буфер) и mimetype (MIME означает многоцелевые расширения электронной почты в Интернете).

Теперь, когда у вас есть этот объект, что с ним делать, зависит от вашего облачного хранилища.

Cloudinary Загрузить изображение

Вы захотите преобразовать свой буфер данных в base64.

Если вы заинтересовались и console.logging newPhoto вы получите следующую строку, это base64:
TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0aGlzIHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIGx1c3Qgb2Yg ...

const cloudinary = require('cloudinary');
cloudinary.config({
  cloud_name: 'fido',
  api_key: process.env.CLOUDINARY_API_KEY,
  api_secret: process.env.CLOUDINARY_API_SECRET,
});
const fileUpload = require('express-fileupload');
app.use(fileUpload());
app.post('/upload', (req, res) => {
  const newPhoto = req.files['photo'].data.toString('base64');
  const type = req.files['photo'].mimetype;

  // Uploads to cloudinary
  cloudinary.v2.uploader.upload(`data:${type};base64,${newPhoto}`, (err, photo) => {
    if (err) {
      console.error(err);
      res.status(400).send(err);
    } else {
      const photoUrl = photo.url;
})

Photo.url - это ваше размещенное облачное изображение, доступное из Интернета. Облачная документация проанализирована и немного упрощена. (Если хотите загрузить видео, просто напишите:

// hasen't worked for me so far
cloudinary.v2.uploader.upload("dog.mp4", 
        { resource_type: "video" },
        function(error, result) { console.log(result); });

Amazon S3 Видео и изображения

Документацию Amazon S3 легко отслеживать и адаптировать. Наиболее распространенные проблемы с stackoverflow связаны с поиском вашего открытого ключа и тем, как сделать ваш магазин общедоступным (чтобы ваша аудитория могла получить доступ к вашему URL-адресу изображения и видео). Это действительно немного сложно.
Имейте в виду, что загрузка видео, конечно же, занимает много времени!

const s3 = new aws.S3({
accessKeyId: process.env.AWS_ACCESS_KEY_ID,
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
region: "us-east-1",
});
app.post('/uplaod', (req, res) => {
  const uploadParams = { Bucket: 'classmate2', Key: '', Body: '' };
  uploadParams.Body = req.files.document.data;
  uploadParams.Key = req.files.document.name;
  s3.upload(uploadParams, function (err, data) {
    if (err) {
      console.log("Error", err);
    } if (data) {
      console.log("Upload Success", data.Location);
})

Ваши данные.Локация - это URL-адрес вашего актива, который вам нужно сделать общедоступным. Вы захотите написать свой объект политики корзины следующим образом

{
  "Version": "2018",
  "Statement": [
    {
      "Sid": "PublicReadGetObject",
      "Action": "s3:GetObject",
      "Effect": "Allow",
      "Resource": "arn:aws:s3:::YOUR_BUCKET_NAME/*",
      "Principal": "*"
    }
  ]
}

Удачной загрузки!