首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Rails API,如何接收使用FormData从本机react发送的照片。

Rails API,如何接收使用FormData从本机react发送的照片。
EN

Stack Overflow用户
提问于 2020-07-30 18:01:59
回答 1查看 690关注 0票数 1

我使用rails作为后端,将本地的rails作为前端,我试图上传一张照片,使用react本机中的格式数据,并使用rails中的活动存储保存它。使用一个模型名Room.rb和has_one_attached :图。

Room.rb

代码语言:javascript
复制
class Room < ApplicationRecord
  has_one_attached :photo
end

这是rails收到的params,有两个(room_name和照片)

代码语言:javascript
复制
{
  "room_name"=>"Guest Room", 
  "photo"=>
    <ActionController::Parameters {
      "uri"=>"file:///Users/MyName/Library/Developer/CoreSimulator/Devices/guest_room.jpg", 
      "name"=>"guest_room.jpg", 
      "type"=>"image/jpg"
    } permitted: true >
}

room_controller.rb来保存和接收文件,如下所示

代码语言:javascript
复制
def create
  @room = Room.create(room_params)
  if @room.save
    render json: RoomSerializer.new(@room).serializable_hash, status: :created
  else
    render json: { errors: @room.errors }, status: :unprocessable_entity
  end
end

我在@room.save里面出了一个错误,说'TypeError -散列键‘uri不是符号:’我希望在我从手机(客户端)选择图像并按保存按钮后,它会自动下载一个图像,这也是我使用FormData从react本机发送的原因。

更新2:

这里是本地上传照片的一部分,

代码语言:javascript
复制
const preparePhoto = (uriPhoto) => {
  // ImagePicker saves the taken photo to disk and returns a local URI to it
  const localUri = uriPhoto;
  const name = localUri.split('/').pop();

  // Infer the type of the image
  const match = /\.(\w+)$/.exec(name);
  const type = match ? `image/${match[1]}` : `image`;

  return [name, type];
};

const createRoom = dispatch => async ({ room_name, uriPhoto }) => {

  const [name, type] = preparePhoto(uriPhoto);
  const photo = { uri: uriPhoto, name, type };
  const room = { room_name, photo };
  const formData = new FormData();

  formData.append('room', JSON.stringify(room));

  const config = { headers: {
    Accept: 'application/json',
    'Content-Type': 'multipart/form-data',
  } };

  try {
    const response = await serverApi.post('/rooms', formData, config);
    dispatch({ type: 'clear_error' });
  } catch (err) {
    console.log('error: ', err);
    dispatch({ type: 'add_error', payload: 'Sorry we have problem' });
  }
};

更新3:

选择图像并将其发送到上下文的源代码

代码语言:javascript
复制
import React, { useState } from 'react';
import Constants from 'expo-constants';
import {
  ActivityIndicator,
  Button,
  Clipboard,
  Image,
  Share,
  StatusBar,
  StyleSheet,
  Text,
  TouchableOpacity,
  View,
} from 'react-native';
import * as ImagePicker from 'expo-image-picker';
import * as Permissions from 'expo-permissions';


const RoomUploadPhoto = ({ uriPhoto, onPhotoChange }) => {
  const [uploading, setUploading] = useState(false);

  const renderUploadingIndicator = () => {
    if (uploading) {
      return <ActivityIndicator animating size="large" />;
    }
  };

  const askPermission = async (type, failureMessage) => {
    const { status, permissions } = await Permissions.askAsync(type);

    if (status === 'denied') {
      alert(failureMessage);
    }
  };

  const handleImagePicked = (pickerResult) => {
    onPhotoChange(pickerResult.uri);
  };

  const takePhoto = async () => {
    await askPermission(
      Permissions.CAMERA,
      'We need the camera permission to take a picture...'
    );
    await askPermission(
      Permissions.CAMERA_ROLL,
      'We need the camera-roll permission to read pictures from your phone...'
    );
    const pickerResult = await ImagePicker.launchCameraAsync({
      allowsEditing: true,
      aspect: [4, 3],
    });

    handleImagePicked(pickerResult);
  };

  const pickImage = async () => {
    await askPermission(
      Permissions.CAMERA_ROLL,
      'We need the camera-roll permission to read pictures from your phone...'
    );
    const pickerResult = await ImagePicker.launchImageLibraryAsync({
      allowsEditing: true,
      aspect: [4, 3],
    });

    handleImagePicked(pickerResult);
  };

  const renderControls = () => {
    if (!uploading) {
      return (
        <View>
          <View style={styles.viewSatu}>
            <Button
              onPress={pickImage}
              title="Pick an image from camera roll"
            />
          </View>
          <View style={styles.viewSatu}>
            <Button onPress={takePhoto} title="Take a photo" />
          </View>          
        </View>
      );
    }
  };

  return (
    <React.Fragment>
      <Text>upload photo</Text>
      {renderUploadingIndicator()}
      {renderControls()}

    </React.Fragment>
  );
};

const styles = StyleSheet.create({
  viewSatu: {
    marginVertical: 8
  }
});

export default RoomUploadPhoto;
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-07-30 22:02:27

确保将File对象或base64内容发布到后端。您的photo只是一个json对象,目前包含文件路径和名称。

请从您的photo中删除room_params参数。

代码语言:javascript
复制
def room_params
  params.require(:room).permit(
    :room_name
  )
end

并在创建photo时附加room

代码语言:javascript
复制
def create
  @room = Room.new(room_params)
  @room.attach params[:photo]
  ...
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/63178821

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档