【问题标题】:Successfully uploaded image to Cloudinary from React Native does not return URL从 React Native 成功上传图片到 Cloudinary 不返回 URL
【发布时间】:2020-12-14 05:40:53
【问题描述】:

我正在尝试将图像从 React Native 应用程序上传到 Cloudinary。 图片出现在仪表板上,但我没有获得secure_url。

这是我的代码:

  async uploadImage(photo: ImagePickerResponse, id: string): Promise<string> {
    return new Promise<string>(async (resolve, reject) => {
      const uploadPreset = 'bbbbbb';
      const cloudName = 'aaaaa';

      const body = new FormData();
      const uri: string =
        Platform.OS === 'android' ? photo.uri : photo.uri.replace('file://', '');
      const type = photo.type;
      const name = `eMia${id}.jpeg`;
      const file = {uri, type, name};
      body.append('file', file);
      body.append('upload_preset', uploadPreset);
      body.append('cloud_name', cloudName);
      const url = `https://api.cloudinary.com/v1_1/${cloudName}/image/upload`;

      fetch(url, {method: 'POST', body})
        .then((res) => {
          // I don't have Body here so i don't have the image url :(
          console.log(res);
          res.json();
        })
        .then((json) => {
          console.log(json);
          const url = json.secure_url;
          console.log(url);
          resolve(url);
        })
        .catch((err) => {
          reject(err);
        });
    });
  }

回复:

【问题讨论】:

    标签: javascript typescript react-native cloudinary


    【解决方案1】:

    React Native 应用程序将照片上传到 Cloudinary 服务器并获取照片的链接。 来自 Image Picker 的文件通过两个步骤上传到 Cloudinary。第一步将照片上传到应用服务器:

    import {DBStorageInteractor} from '../interfaces';
    import {BASE_URL} from '../../../config/constants';
    import ImageResizer from 'react-native-image-resizer';
    import {ImagePickerResponse} from 'react-native-image-picker';
    
        
      async uploadImage(photo: ImagePickerResponse, id: string): Promise<string> {
        return new Promise<string>(async (resolve, reject) => {
          if (!photo) {
            reject(Error('Photo is not presented'));
            return;
          }
          this.getBody(photo, id)
            .then((body) => {
              const headers = {
                Accept: 'application/json',
                'Content-Type': 'application/json',
              };
              const options = {
                method: 'POST',
                body: body,
                headers: headers,
              };
              fetch(`${BASE_URL()}/api/images/upload`, options)
                .then((response) => response.json())
                .then((response) => {
                  const secureUrl = response.secure_url;
                  console.log('Uploaded successfully. Url=', secureUrl);
                  resolve(secureUrl);
                })
                .catch((error) => {
                  const message = `Failed uploading. Error=${error}`;
                  console.log(message);
                  reject(Error(message));
                });
            })
            .catch((error) => {
              reject(error);
            });
        });
      }
    
      getBody(photo: ImagePickerResponse, id: string): Promise<string> {
        return new Promise((resolve, reject) => {
          if (photo.fileSize < 100000) {
            resolve(
              JSON.stringify({
                img: photo.data,
                name: `eMia${id}.${this.getFileExtension(photo.uri)}`,
              })
            );
          } else {
            ImageResizer.createResizedImage(photo.uri, 400, 400, 'JPEG', 80)
              .then(({uri}) => {
                RNFS.readFile(uri, 'base64')
                  .then((data) => {
                    resolve(
                      JSON.stringify({
                        img: data,
                        name: `eMia${id}.${this.getFileExtension(photo.uri)}`,
                      })
                    );
                  })
                  .catch((error) => {
                    reject(error);
                  });
              })
              .catch((error) => {
                reject(error);
              });
          }
        });
      }
    
      getFileExtension(filename) {
        return filename.slice((filename.lastIndexOf(".") - 1 >>> 0) + 2);
      }
    

    图片。 1. 客户端从Image Picker上传照片到服务器端,获取照片链接。

    在第二步服务器端(在 NodeJS 上)处理两个步骤的请求。它将请求中的文件图像写入临时目录,然后将其上传到 Cloudinary 服务器:

    const {Router} = require('express')
    const router = Router()
    const cloudinary = require('cloudinary').v2;
    const fs = require('fs')
    // /api/images/upload
    router.post('/upload', async (req, res) => {
        try {
          const file = req.body.img;
          const name = req.body.name;
          const path = `tmp/${name}`;
          // Write received fire in temporary folder
          fs.writeFile(path, file, 'base64', (err) => {
            if (err) {
              console.log(err);
              throw err
            }
            // Upload file to the Cloudinary server
            cloudinary.uploader.upload(path)
              .then((results) => {
                res.status(200).json(results)
              })
              .catch((error) => {
                res.status(400).json(error)
              });
          })
        } catch (error) {
          res.status(500).json(error)
        }
      }
    )
    

    图片。 2. 在NodeJS服务器上处理请求'/upload'。

    在服务器端配置 Cloudinary:

    const cloudinary = require('cloudinary').v2;
    
    require('dotenv').config();
    
    cloudinary.config({
      cloud_name: process.env.cloud_name,
      api_key: process.env.api_key,
      api_secret: process.env.api_secret,
    });
    

    文件 .env(在项目的根目录中)包含以下参数:

    cloud_name=<Cloudinary cloud name>
    api_key=<API key from the Cloudinary project settings>
    api_secret=<API secret from the Cloudinary project settings>
    

    【讨论】:

      【解决方案2】:

      你能试试下面的代码吗:

      import React from "react";
      import ReactDOM from "react-dom";
      
      import "./styles.css";
      
      class Upload extends React.Component {
        processFile = async e => {
          var file = e.target.files[0];
          var formdata = new FormData();
      
          formdata.append("file", file);
          formdata.append("cloud_name", "shirly");
          formdata.append("upload_preset", "my-preset");
      
          let res = await fetch(
            "https://api.cloudinary.com/v1_1/emia/auto/upload",
            {
              method: "post",
              mode: "cors",
              body: formdata
            }
          );
      
          let json = await res.json();
          console.log(JSON.stringify(json.secure_url));
        };
      
        render() {
          return (
            <div>
              <h3>Upload</h3>
              <input type="file" onChange={this.processFile} />
            </div>
          );
        }
      }
      ReactDOM.render(<Upload />, document.getElementById("container"));
      

      【讨论】:

      • 谢谢你的回答。据我了解,您建议使用 'mode: "cors",' 选项。我尝试过这个。相同的结果:图像在服务器上,但我没有在响应中得到它的 url
      猜你喜欢
      • 2022-01-14
      • 2022-01-12
      • 2023-02-08
      • 2019-05-07
      • 2018-06-08
      • 2017-06-29
      • 1970-01-01
      • 2015-08-24
      • 2016-03-10
      相关资源
      最近更新 更多