You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过React Native(Expo)实时获取相机图片并上传至Azure Blob存储?

Expo相机实时拍照上传至Azure Blob存储方案

你已经实现了通过表单上传图片到Azure Blob的Flask后端,现在只需要在Expo端完成实时拍照并构造符合后端要求的请求即可,以下是完整实现步骤:

一、Expo前端实现

1. 安装必要依赖

首先在Expo项目中安装相机相关依赖:

npx expo install expo-camera expo-image-picker

2. 相机拍照与上传代码示例

创建一个拍照上传组件,核心逻辑是调用相机拍照、将图片转为FormData、附带其他表单字段发送POST请求到你的Flask接口:

import { useState, useEffect } from 'react';
import { View, Button, Alert, Text } from 'react-native';
import { Camera } from 'expo-camera';

export default function CameraUploadScreen() {
  const [hasPermission, setHasPermission] = useState(null);
  const [cameraRef, setCameraRef] = useState(null);
  const [type, setType] = useState(Camera.Constants.Type.back);

  // 请求相机权限
  useEffect(() => {
    (async () => {
      const { status } = await Camera.requestCameraPermissionsAsync();
      setHasPermission(status === 'granted');
    })();
  }, []);

  // 拍照并上传
  const takePictureAndUpload = async () => {
    if (cameraRef) {
      try {
        // 拍照获取图片
        const photo = await cameraRef.takePictureAsync({ quality: 0.8 });
        
        // 构造FormData,匹配后端接收的字段
        const formData = new FormData();
        
        // 添加图片文件
        formData.append('file', {
          uri: photo.uri,
          name: `incident_${Date.now()}.jpg`, // 自定义文件名
          type: 'image/jpeg'
        });
        
        // 添加其他表单字段(根据业务需求填写实际值)
        formData.append('damage_type', '碰撞');
        formData.append('damage_parts', '保险杠');
        formData.append('location_address', '北京市朝阳区XX路');
        formData.append('geolocation_latitude', '39.9042');
        formData.append('geolocation_longitude', '116.4074');
        formData.append('datetime', new Date().toISOString());
        formData.append('created_by', 'user123');
        formData.append('created_on', new Date().toISOString());
        formData.append('modified_by', 'user123');
        formData.append('modified_on', new Date().toISOString());
        formData.append('customer_id', 'cust456');
        
        // 发送POST请求到Flask后端
        const response = await fetch('http://你的Flask服务器地址/api/addincident', {
          method: 'POST',
          body: formData,
          headers: {
            'Content-Type': 'multipart/form-data'
          }
        });
        
        if (response.ok) {
          const imageUrl = await response.text();
          Alert.alert('上传成功', `图片地址:${imageUrl}`);
        } else {
          Alert.alert('上传失败', '请检查网络或后端服务');
        }
      } catch (error) {
        console.error('拍照或上传出错:', error);
        Alert.alert('错误', '拍照或上传过程中出现问题');
      }
    }
  };

  if (hasPermission === null) {
    return <View />;
  }
  if (hasPermission === false) {
    return <Text>无相机访问权限</Text>;
  }

  return (
    <View style={{ flex: 1 }}>
      <Camera 
        style={{ flex: 1 }} 
        type={type}
        ref={ref => setCameraRef(ref)}
      />
      <View style={{ position: 'absolute', bottom: 20, alignSelf: 'center' }}>
        <Button title="拍照并上传" onPress={takePictureAndUpload} />
      </View>
    </View>
  );
}

二、Flask后端优化修正

你的现有后端代码已经可以处理上传请求,但存在两个必须修正的问题:

1. 地理位置字段取值错误

原代码中geolocation_longitude错误地取了geolocation_latitude的值,导致经纬度数据混乱,修正如下:

geolocation_longitude = request.form.get('geolocation_longitude') # 原代码写的是geolocation_latitude

2. 异常处理语法错误

原代码中print('Exception=' + Exception)是语法错误,无法正确打印异常信息,修正为:

try:
    blob_service.create_blob_from_stream(container, filename, file)
except Exception as e:
    print(f'Exception={str(e)}')
    pass

3. 可选优化:添加状态码返回

为了让前端更清晰地判断请求结果,建议在返回时附带HTTP状态码:

# 上传成功返回
return image_filepath, 200

# 若上传失败,可返回错误提示与状态码
# return '图片上传失败', 500

关键注意事项

  • Expo中构造FormData时,文件必须包含uri、name、type三个字段,否则后端无法识别为文件类型
  • 本地测试时,Flask服务器需启动为app.run(host='0.0.0.0', port=5000),确保同一局域网内的Expo设备可以访问
  • 可通过takePictureAsync的quality参数调整图片质量,平衡文件大小与清晰度

内容的提问来源于stack exchange,提问作者Tharshika Elangovan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 16:01:02