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

 app.json:

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

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

 我的RN代码:

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>
  uploadFile: (data) => common({ url: urls.h5.uploadFile, data, method: 'post', headers: { 'content-type': 'multipart/form-data' } }),

 官方RN代码:

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接收文件上传:

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库。

expo install expo-image-picker

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

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函数将该数据发送到后端。

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

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/