使用Carrierwave将图像从React上传到Rails API

时间:2018-05-24 14:09:54

标签: ruby-on-rails ruby reactjs api carrierwave

我尝试使用carrierwave gem将反应应用中的图像上传到rails api。到目前为止,我已经尝试了很多东西,并且在没有找到解决方案的情况下在互联网上随处可见。

这是我发送的请求 request from react

但是在rails app上,事件参数未被传递

  

07:57:37 api.1 |开始PATCH" / api / v1 / events / 8"对于127.0.0.1 at   2018-05-24 07:57:37 -0600 07:57:37 api.1 |处理方式   Api :: V1 :: EventsController#update as / 07:57:37 api.1 |
  参数:{" id" =>" 8"} 07:57:37 api.1 |事件加载(4.9ms)SELECT   events。* FROM events WHERE eventsid = 8 LIMIT 1 07:57:37   api.1 |在7ms完成401未授权(ActiveRecord:4.9ms)   07:57:37 api.1 | 07:57:37 api.1 | 07:57:37 api.1 |七时57分37秒   api.1 | ActionController :: ParameterMissing(param缺失或者   value为空:event):07:57:37 api.1 | 07:57:37 api.1 |   app / controllers / api / v1 / events_controller.rb:92:event_params' 07:57:37 api.1 | app/controllers/api/v1/events_controller.rb:56:in 更新'

如果我在请求正文中使用JSON.Stringify发送,它会进入更新函数,但是carrierwave什么都不做。

我知道Carrierwave正在运行,因为如果使用ActiveAdmin上传图像,它可以正常工作。

以下是我创建请求的操作

export const uploadMainImage = (event, eventId) => {

    return (dispatch) => {
        //dispatch({ type: UPLOAD_IMAGE_REQUEST });
        //console.log(window.location);
        let upload = {
            event
        }
        const requestOptions = {
            method: 'PATCH',
            headers: uploadAuthHeader(),
            body: upload
        };
        console.log("request:");
        console.log(requestOptions);
        //window.fetch(window.location.origin + '/api/v1/events/image_upload/' + eventId, requestOptions)
        window.fetch(window.location.origin + '/api/v1/events/' + eventId, requestOptions)
          .then(response => response.json())
          .then(response => {
              dispatch({ type: UPLOAD_IMAGE_SUCCESS, payload: response });
          })
          .catch(error => {
                //console.log(error);
                dispatch({ type: UPLOAD_IMAGE_FAILURE, payload: error })
          })
    };
}

这是标题:

export function uploadAuthHeader() {
    // return authorization header with jwt token
    let user = JSON.parse(localStorage.getItem('user'));

    if (user && user.auth_token) {
        return { 

            //'Content-Type': 'application/json',
            'Content-Type': 'multipart/form-data',
            'Authorization': 'Bearer ' + user.auth_token 
        };
    } else {
        return {};
    }
}

这是我处理react-dropzone

中文件选择的地方
readFile(files) {


        const event = {
            imagen: files[0]
        }

        this.props.uploadMainImage(event, this.props.match.params.eventId);

    }

在轨道方面,这是我的模型

class Event < ApplicationRecord
  belongs_to :user
  mount_uploader :imagen, ImagenUploader
end
来自Carrierwave的

和Uploader未默认修改。

UPDATE ------ 这是我的event_controller.rb,我使用控制器的默认udate方法

module Api
  module V1
    class EventsController < ApiController
      before_action :authenticate_request, only: [:index, :create, :destroy]
      before_action :set_event, only: [:show, :update, :destroy, :image_upload]


      # GET /events
      # Entrego los eventos especificos del usuario loggeado.
      def index
        @events = @current_user.events
        if params[:page]
          @events = @events.page(params[:page]).per(params[:per_page])
          pageCount = @events.total_pages
        else
          #@events = Event.order('fecha ASC')
          pageCount = 1
        end
        render json: { events: @events, meta: { pages: pageCount, records: @events.count } }
      end

      # GET /events/1
      def show
        render json: @event
      end

      # GET /events/upcoming
      def upcoming
        @events = Event.where('fecha >= ?', Date.today).order(:fecha)
        if params[:page]
          @events = @events.page(params[:page]).per(params[:per_page])
          pageCount = @events.total_pages
        else
          #@events = Event.order('fecha ASC')
          pageCount = 1
        end

        render json: { events: @events, meta: { pages: pageCount, records: Event.count } }
      end

      # POST /events
      def create
        @event = Event.new(event_params)
        #@event.imagen = event_params[:imagen][:preview]

        if @event.save
          #@event.imagen = event_params[:imagen][:preview]
          render json: @event, status: :created#, location: @event
        else
          render json: @event.errors, status: :unprocessable_entity
        end
      end

      # PATCH/PUT /events/1
      def update
        if @event.update(event_params)
          render json: @event
        else
          render json: @event.errors, status: :unprocessable_entity
        end
      end


      # DELETE /events/1
      def destroy
        @event.destroy
      end

      private
        # Use callbacks to share common setup or constraints between actions.
        def set_event
          @event = Event.find(params[:id])
        end

        # Only allow a trusted parameter "white list" through.
        def event_params
          params.require(:event).permit!
        end
    end
  end
end

同样来自Active Admin,event.rb文件,我只允许:imagen字段,当我从活动管理员上传时,它可以在控制器中没有任何更改的情况下正常工作。

ActiveAdmin.register Event do
# See permitted parameters documentation:
# https://github.com/activeadmin/activeadmin/blob/master/docs/2-resource-customization.md#setting-up-strong-parameters
#
# permit_params :list, :of, :attributes, :on, :model
#
# or
#
# permit_params do
#   permitted = [:permitted, :attributes]
#   permitted << :other if params[:action] == 'create' && current_user.admin?
#   permitted
# end
permit_params :nombre, :user_id, :hora, :fecha, :lugar, :meta, :inicio_inscripcion, 
    :fin_inscripcion, :costo_inscripcion, :pagina_web, :logo, :numero_inicial, 
    :nombre_contacto, :telefono_contacto, :email_contacto, :imagen, :string

end

我需要一只手来弄清楚如何将我的React应用程序中的图像上传到Rails API。

第二次更新

这是来自active_admin的POST请求

开始发布&#34; / admin / events / 6&#34; for :: 1 at 2018-05-24 11:54:48 -0600 11:54:48 api.1 |由Admin :: EventsController处理#update为HTML 11:54:48 api.1 |参数:{&#34; utf8&#34; =&gt;&#34;✓&#34;,&#34; authenticity_token&#34; =&gt;&#34; 9BqST8qDLEJbDlfd6Xs / + YCDMy9qPeCcbOOxbjIGbDoTBRaGAVRU48rqI + E3kD9ORbsiBguS / emJN9JIM + StuQ = =&#34;,&#34; event&#34; =&gt; {&#34; user_id&#34; =&gt;&#34; 1&#34;,&#34; nombre&#34; =&gt;& #34; Carrera con Foto&#34;,&#34; hora_inicio(1i)&#34; =&gt;&#34; 2018&#34;,&#34; hora_inicio(2i)&#34; =&gt;& #34; 5&#34;,&#34; hora_inicio(3i)&#34; =&gt;&#34; 24&#34;,&#34; hora_inicio(4i)&#34; =&gt;&#34 ;&#34;,&#34; hora_inicio(5i)&#34; =&gt;&#34;&#34;,&#34; fecha_inicio(1i)&#34; =&gt;&#34;& #34;,&#34; fecha_inicio(2i)&#34; =&gt;&#34;&#34;,&#34; fecha_inicio(3i)&#34; =&gt;&#34;&#34 ;,&#34; hora(1i)&#34; =&gt;&#34; 2018&#34;,&#34; hora(2i)&#34; =&gt;&#34; 5&#34;, &#34; hora(3i)&#34; =&gt;&#34; 24&#34;,&#34; hora(4i)&#34; =&gt;&#34;&#34;,&# 34; hora(5i)&#34; =&gt;&#34;&#34;,&#34; fecha(1i)&#34; =&gt;&#34; 2018&#34;,&#34; fecha(2i)&#34; =&gt;&#34; 5&#34;,&#34; fecha(3i)&#34; =&gt;&#34; 27&#34;,&#34; lugar&# 34; =&gt;&#34; Villa Olimpica&#34;,&#34; meta&#34; =&gt;&#34;&# 34;,&#34; inicio_inscripcion(1i)&#34; =&gt;&#34; 2018&#34;,&#34; inicio_inscripcion(2i)&#34; =&gt;&#34; 5&#34; ,&#34; inicio_inscripcion(3i)&#34; =&gt;&#34; 17&#34;,&#34; fin_inscripcion(1i)&#34; =&gt;&#34; 2018&#34;,& #34; fin_inscripcion(2i)&#34; =&gt;&#34; 5&#34;,&#34; fin_inscripcion(3i)&#34; =&gt;&#34; 25&#34;,&#34 ; costo_inscripcion&#34; =&gt;&#34; 123&#34;,&#34; pagina_web&#34; =&gt;&#34;&#34;,&#34; logo&#34; =&gt;&# 34;&#34;,&#34; numero_inicial&#34; =&gt;&#34; 100&#34;,&#34; nombre_contacto&#34; =&gt;&#34; Hector Toro&#34;,&# 34; telefono_contacto&#34; =&gt;&#34; 50498761065&#34;,&#34; email_contacto&#34; =&gt;&#34; htorohn@gmail.com" ;,&#34; imagen&#34; =&gt;#,@ original_filename =&#34; IMG_0008.PNG&#34;,@ content_type =&#34; image / png&#34;,@ header =&#34; Content-Disposition:form-data;命名= \&#34;活动[imagen可] \&#34 ;; filename = \&#34; IMG_0008.PNG \&#34; \ r \ nConContent-Type:image / png \ r \ n&#34;&gt;},&#34; commit&#34; =&gt;&#34 ;更新活动&#34;,&#34; id&#34; =&gt;&#34; 6&#34;}

更新3。

我提出了Bill提出的更改,但事件参数仍然没有进入rails应用程序。

07:59:02 api.1 |开始PATCH&#34; / api / v1 / events / 8&#34;对于127.0.0.1在2018-05-25 07:59:02 -0600 07:59:02 api.1 |由Api :: V1 :: EventsController#update处理为 / 07:59:02 api.1 |参数:{&#34; id&#34; =&gt;&#34; 8&#34;} 07:59:02 api.1 |事件加载(0.7ms)SELECT events。* FROM events WHERE eventsid = 8 LIMIT 1 07:59:02 api.1 |在8ms完成401未授权(ActiveRecord:0.7ms) 07:59:02 api.1 | 07:59:02 api.1 | 07:59:02 api.1 |
07:59:02 api.1 | ActionController :: ParameterMissing(param丢失或值为空:event): 07:59:02 api.1 |
07:59:02 api.1 | app / controllers / api / v1 / events_controller.rb:95:在event_params' 07:59:02 api.1 | app/controllers/api/v1/events_controller.rb:56:in更新&#39;

enter image description here

1 个答案:

答案 0 :(得分:0)

因此,查看您的主动管理员允许参数与您自己的EventsController允许参数,似乎与您从Javascript发送的内容相比,允许和预期的内容存在差异。我从您的代码中推断出您的events表架构。我无法在本地重现您的代码,因为我没有全部。但这是我认为可行的:

您需要像正在尝试一样在正文中传递图像文件数据,但需要使用参数名称(event[imagen])在正文中对其进行编码。试试这个:

export const uploadMainImage = (imageFile, eventId) => {

    let data = new FormData();
    data.append("event[imagen]", imageFile);

    return (dispatch) => {
        //dispatch({ type: UPLOAD_IMAGE_REQUEST });
        //console.log(window.location);
        const requestOptions = {
            method: 'PATCH',
            headers: uploadAuthHeader(),
            body: data
        };
        console.log("request:");
        console.log(requestOptions);
        window.fetch(window.location.origin + '/api/v1/events/' + eventId, requestOptions)
          .then(response => response.json())
          .then(response => {
              dispatch({ type: UPLOAD_IMAGE_SUCCESS, payload: response });
          })
          .catch(error => {
                //console.log(error);
                dispatch({ type: UPLOAD_IMAGE_FAILURE, payload: error })
          })
    };
}


readFile(files) {
    var imageFile = files[0];  // assumes files[0] is from your file form input
    this.props.uploadMainImage(imageFile, this.props.match.params.eventId);
}