使用React Native、Expo ImagePicker、Rails、Axios和Paperclip进行图片上传

7

目前,关于Rails和Paperclip的后端部分都能正常工作。我已经设置好了当您创建新的帖子时,该帖子中的图像将上传到AWS S3。在后端方面一切正常。我还使用Expo的ImagePicker从用户的相机胶卷中获取图像。然而,当我尝试在React Native中使用formData通过Axios发布内容时,我遇到了以下错误:

Paperclip::AdapterRegistry::NoHandlerError - No handler found for 
"file:///Users/jimmy/Library/Developer/CoreSimulator/Devices/A3590E6A-
281B-4EFB-868C-9F5311718832/data/Containers/Data/Application/CB5ED945-
AA87-4E36-83B6-71426759C70C/Library/Caches/ExponentExperienceData/%2540anonymous%252Fartis
-ed15f4f4-b8d6-460f-a1b3-e06d546eda2a/ImagePicker/B3162237-9BCD-4721-
BDF2-D66BC047A6C0.jpg"

这是一些我的代码片段:
在PostForm中的React Native提交处理程序:
onSubmit() {
    const { navigate } = this.props.navigation;
    return () => {
      const formData = new FormData();
      formData.append("post[title]", this.state.title);
      formData.append("post[body]", this.state.body);
      formData.append("post[user_id]", this.props.currentUser.id);
      formData.append("post[image]", this.state.image);
      this.props.createPost(formData).then((res) => {
        if (res.type) {
          navigate("Explore");
        }
      });
    };
  }

使用ImagePicker获取图像URI,以便在父组件中的PostForm中显示预览并更新图像URI:

_pickImage = async () => {
    let pickerResult = await ImagePicker.launchImageLibraryAsync({
      allowsEditing: true,
      aspect: [4, 3],
    });
    if (pickerResult.cancelled) {
      return;
    }
    this.setState({image: pickerResult.uri});
    this.props.updatePostWithImage(pickerResult.uri);
  };

动作和API调用:

export const createPost = (post) => dispatch => (
  postPost(post).then((res) => {
    return dispatch(receivePost(res.data));
  }).catch((errors) => {
  })
);

const url = "http://localhost:3000";

export const postPost = (post) => {
  return axios({
    method: 'POST',
    url: `${url}/api/posts`,
    dataType: "JSON",
    contentType: false,
    processData: false,
    data: post
  });
};

文章控制器:

def create
  @post = Post.new(post_params)
  if @post.save
    render :show
  else
    render json: @post.errors.full_messages, status: 422
  end
end

def post_params
  params.require(:post).permit(:title, :body, :image, :user_id)
end

文章模型:

class Post < ApplicationRecord
  validates :title, :body, presence: true

  belongs_to :user

  has_attached_file :image, default_url: "https://res.cloudinary.com/jun/image/upload/v1506659435/Doge_sggjpf.jpg"
  validates_attachment_content_type :image, content_type: /\Aimage\/.*\z/
end

Axios POST请求发送给Rails的参数:

Parameters: {"post"=>{"title"=>"Test", "body"=>"Testing", "user_id"=>"1", "image"=>"file:///Users/jimmy/Library/Developer/CoreSimulator/Devices/A3590E6A-281B-4EFB-868C-9F5311718832/data/Containers/Data/Application/CB5ED945-AA87-4E36-83B6-71426759C70C/Library/Caches/ExponentExperienceData/%2540anonymous%252Fartis-ed15f4f4-b8d6-460f-a1b3-e06d546eda2a/ImagePicker/B3162237-9BCD-4721-BDF2-D66BC047A6C0.jpg"}}

我不太确定发生了什么。我认为参数看起来很好,但我认为可能会缺少许多Paperclip所需的东西。但我不知道如何获取它们。我尝试了到处搜索,但没有找到可以帮助的解决方案。我对使用这些技术还比较新,所以请多包涵,哈哈。
如果有其他信息可以添加以帮助调试此问题,请告诉我。提前致谢!
1个回答

7

好的,我找到了问题并将其修复了。我忘记在后端添加Paperclip所需的额外信息。我仅对onSubmit处理程序函数进行了更改。

  onSubmit() {
    const { navigate } = this.props.navigation;
    return () => {
      let uriParts = this.state.image.split('.');
      let fileType = uriParts[uriParts.length - 1];
      console.log(fileType);
      const formData = new FormData();
      formData.append("post[title]", this.state.title);
      formData.append("post[body]", this.state.body);
      formData.append("post[user_id]", this.props.currentUser.id);
      formData.append("post[image]", {
        uri: this.state.image,
        name: `${this.state.title}.${fileType}`,
        type: `image/${fileType}`,
      });
      this.props.createPost(formData).then((res) => {
        if (res.type) {
          navigate("Explore");
        }
      });
    };
  }

设置图片的URI、名称和文件类型解决了问题。现在我可以从相机胶卷中选择一张图片,并成功地创建一个帖子,使用那张图片上传到AWS S3,使用paperclip。:D


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接