React Native expo项目使用expo-image-picker上传图片

app.json:

https://docs.expo.dev/versions/latest/sdk/imagepicker/

javascript 复制代码
{
  "expo": {
    "plugins": [
      [
        "expo-image-picker",
        {
          "photosPermission": "The app accesses your photos to let you share them with your friends."
        }
      ]
    ]
  }
}

我的RN代码:

javascript 复制代码
import * as ImagePicker from 'expo-image-picker'


  const handleUploadAvatar = async () => {
    try {
      let result = await ImagePicker.launchImageLibraryAsync({
        mediaTypes: ImagePicker.MediaTypeOptions.All,
        base64: true,
        //allowsEditing: true,
        //aspect: [4, 3],
        //quality: 1,
      })
      if (!result.canceled) {
        const formData = new FormData()
        let uri = result.assets[0].uri
        let uriArr = uri.split('/')
        let name = uriArr[uriArr.length - 1]
        console.log(uri)
        setAvatar(uri)
        formData.append('file', {
          uri,
          name,
          //type: result.assets[0].type,
          type: 'image/jpeg',
        })
        Api.h5.uploadFile(formData).then((res) => {
          console.log(res)
          if (res.code === 200) {
            console.log('成功')
          }
        })
      } else {
        console.log('取消文件选择')
      }
    } catch (error) {
      console.log('选择文件时出错', error)
    }
  }




        <View style={style.mRegisterRow}>
          <View style={style.mRegisterAvavtarTextWrap}>
            <Text style={style.mRegisterAvavtarText}>头像</Text>
          </View>
          {avatar ? (
            <TouchableWithoutFeedback onPress={handleUploadAvatar}>
              <Image
                source={{ uri: avatar }}
                style={style.mRegisterAvatar}
              ></Image>
            </TouchableWithoutFeedback>
          ) : (
            <View style={style.mRegisterUploadIcoWrap}>
              <Icon
                name={'add'}
                onPress={handleUploadAvatar}
                style={style.mRegisterUploadIcon}
              ></Icon>
            </View>
          )}
        </View>
javascript 复制代码
  uploadFile: (data) => common({ url: urls.h5.uploadFile, data, method: 'post', headers: { 'content-type': 'multipart/form-data' } }),

官方RN代码:

javascript 复制代码
import React, { useState, useEffect } from 'react';
import { Button, Image, View, Platform } from 'react-native';
import * as ImagePicker from 'expo-image-picker';

export default function ImagePickerExample() {
  const [image, setImage] = useState(null);

  const pickImage = async () => {
    // No permissions request is necessary for launching the image library
    let result = await ImagePicker.launchImageLibraryAsync({
      mediaTypes: ImagePicker.MediaTypeOptions.All,
      allowsEditing: true,
      aspect: [4, 3],
      quality: 1,
    });

    console.log(result);

    if (!result.canceled) {
      setImage(result.assets[0].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 }} />}
    </View>
  );
}

后端node接收文件上传:

javascript 复制代码
const multer = require('multer')

const storage = multer.diskStorage({
  destination: (req, file, cb) => {
    const NODE_ENV = process.env.NODE_ENV || 'development'
    let tempPath = ''
    if (NODE_ENV === 'development') {
      tempPath = '/temp/uploadForDev/upload'
    } else if (NODE_ENV === 'production') {
      tempPath = '/temp/uploadForProd/upload'
    } else if (NODE_ENV === 'codesandbox') {
      tempPath = 'uploadForCodesandbox/upload'
    }
    cb(null, tempPath)
  },
  filename: (req, file, cb) => {
    cb(null, `${Date.now()}-${file.originalname}`)
  },
})

const uploadImgMulter = multer({ storage })

//上传
const uploadFile = (req, res) => {
  res.send({
    code: 200,
    data: { 
      ...req.file, 
      filename: 'upload/' + req.file.filename 
    },
    message: '上传成功',
  })
}



  app.post(urls.light.uploadFile, uploadImgMulter.single('file'),  (req, res) => commonGroup({ req, res, myRoleGroup: roleGroup.notNeeedLogin, callback: uploadFile }) )

chatgpt的回答


expo-image-picker 图片上传

要使用Expo的ImagePicker库进行图片上传,您可以按照以下步骤操作。

首先,确保您已在项目中安装了Expo的ImagePicker库。

bash 复制代码
expo install expo-image-picker

然后,您可以使用以下代码来选择图片并上传:

javascript 复制代码
import React, { useState, useEffect } from 'react';
import { Button, Image, View } from 'react-native';
import * as ImagePicker from 'expo-image-picker';

const ImagePickerExample = () => {
  const [image, setImage] = useState(null);

  useEffect(() => {
    (async () => {
      // 请求权限
      const { status } = await ImagePicker.requestMediaLibraryPermissionsAsync();
      if (status !== 'granted') {
        console.log('拒绝访问图片库权限!');
      }
    })();
  }, []);

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

    console.log(result);

    if (!result.cancelled) {
      // 设置选择的图片
      setImage(result.uri);

      // 上传图片的逻辑
      // ...
    }
  };

  return (
    <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
      <Button title="选择图片" onPress={pickImage} />
      {image && <Image source={{ uri: image }} style={{ width: 200, height: 200, marginTop: 20 }} />}
    </View>
  );
};

export default ImagePickerExample;

此示例使用Button和Image组件创建一个简单的界面,点击按钮将触发选择图片的逻辑。选择图片后,将通过设置useState来更新图像状态,并将图像显示在屏幕上。

在pickImage函数中,使用ImagePicker.launchImageLibraryAsync方法来打开本地图库,您可以根据自己的需求配置options参数。选择图片后,将在控制台中打印结果。您可以根据需要将选中的图片上传到服务器。

请注意,在使用ImagePicker之前,您需要在app.json文件中的expo.permissions字段中添加相应的权限(例如:READ_EXTERNAL_STORAGE)。

希望这可以帮助到您!如果您有任何其他问题,请随时提问。

使用图片绝对路径,把图片上传到后端

要使用图片的绝对路径将其上传到后端,您可以使用FormData对象来创建一个包含文件的表单数据,并使用fetch函数将该数据发送到后端。

以下是一个使用绝对路径上传图片的示例代码:

javascript 复制代码
import React, { useState } from 'react';
import { Button, Image, View } from 'react-native';
import * as ImagePicker from 'expo-image-picker';

const ImagePickerExample = () => {
  const [image, setImage] = useState(null);

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

    if (!result.cancelled) {
      // 设置选择的图片
      setImage(result.uri);

      // 上传图片到后端
      uploadImage(result.uri);
    }
  };

  const uploadImage = async (uri) => {
    // 创建FormData对象
    const formData = new FormData();
    formData.append('image', { uri, name: 'image.jpg', type: 'image/jpeg' });

    try {
      const response = await fetch('https://your-api-endpoint', {
        method: 'POST',
        body: formData,
        headers: {
          'Content-Type': 'multipart/form-data',
        },
      });

      if (response.status === 200) {
        console.log('图片上传成功');
      } else {
        console.log('图片上传失败');
      }
    } catch (error) {
      console.log('上传图片时出错', error);
    }
  };

  return (
    <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
      <Button title="选择图片" onPress={pickImage} />
      {image && <Image source={{ uri: image }} style={{ width: 200, height: 200, marginTop: 20 }} />}
    </View>
  );
};

export default ImagePickerExample;

uploadImage函数中,我们创建了一个FormData对象并使用append方法将文件添加到表单数据中。我们指定了文件的名称为image.jpg,文件类型为image/jpeg。然后,我们使用fetch函数将该表单数据发送到后端的API端点。

请将https://your-api-endpoint替换为您实际的后端API的地址。您还可以根据需要配置其他请求参数。

注意:在使用fetch发送请求时,确保设置了正确的请求头Content-Typemultipart/form-data,以便服务器正确解析请求。

希望这可以帮助到您!如果您有任何其他问题,请随时提问。

参考链接:

https://chat.xutongbao.top/

https://docs.expo.dev/versions/latest/sdk/imagepicker/

相关推荐
码事漫谈19 分钟前
解决 Anki 启动器下载错误的完整指南
前端
im_AMBER39 分钟前
Web 开发 27
前端·javascript·笔记·后端·学习·web
蓝胖子的多啦A梦1 小时前
低版本Chrome导致弹框无法滚动的解决方案
前端·css·html·chrome浏览器·版本不同造成问题·弹框页面无法滚动
玩代码1 小时前
vue项目安装chromedriver超时解决办法
前端·javascript·vue.js
訾博ZiBo1 小时前
React 状态管理中的循环更新陷阱与解决方案
前端
StarPrayers.2 小时前
旅行商问题(TSP)(2)(heuristics.py)(TSP 的两种贪心启发式算法实现)
前端·人工智能·python·算法·pycharm·启发式算法
一壶浊酒..2 小时前
ajax局部更新
前端·ajax·okhttp
苏打水com2 小时前
JavaScript 面试题标准答案模板(对应前文核心考点)
javascript·面试
Wx-bishekaifayuan2 小时前
基于微信小程序的社区图书共享平台设计与实现 计算机毕业设计源码44991
javascript·vue.js·windows·mysql·pycharm·tomcat·php
DoraBigHead3 小时前
React 架构重生记:从递归地狱到时间切片
前端·javascript·react.js