关于ruby:从React前端的文件上传中获取Rails后端的文件名

Get filename in Rails backend from file upload in React frontend

我在React中有一个文件上传组件,可以对我的Rails API进行POST:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class uploadFormState {
  @observable file;

  constructor() {
     this.file = '';
  }

  @action.bound setFile(file){
   this.file = file[0];
   this.fileName = file[0].name;
  }

  @action.bound uploadFile() {
    $.ajax({
        url: AppConstants.APIEndpoints.USERLOCATIONS + '/1/photos/1/upload',
        headers: {"Authorization": localStorage.getItem('authToken') },
        data: this.file,
        processData: false,
        contentType: false,
        type: 'POST',
        success: function (data) {
            alert(this.data.name +" uploaded successfully!");
        }
     });
   }
}

export default new uploadFormState();

正如您在数据字段中看到的那样,我正在尝试将原始文件名传递到rails后端。问题是,我不知道如何获取这些数据参数。

我的上传方法如下:

1
2
3
  def upload
    @photo.upload_model(request.body)
  end

类方法" upload_model"如下所示:

1
2
3
4
5
6
7
8
9
10
11
  def upload_model(model_file)
    model = StorageBucket.files.new(
    key:"models/#{id}",
    body: model_file.read,
    public: true
    )

    model.save

    update_columns model_url: model.public_url
  end

我尝试将ajax调用中的data字段更改为data: {file: this.file, fileName: this.file.name},但是我不确定如何从rails侧访问这两个参数。如果我以这种方式更改数据参数,则会导致它上载object Object文本。 request.bodyStringIOruby类型。该方法本身在数据字段为this.file时有效(即,它将文件上传到Google存储空间),但是文件名丢失了扩展名,这并不理想。

总而言之,如何在Rails后端访问上载的文件名?


您是否尝试过使用FormData?在您的情况下,它将是:

JS:

1
2
3
4
5
6
7
8
9
10
11
12
// Use FormData to build params

let form = new FormData();
form.append("file_name", file[0].name);

// Send form as part of ajax post

$.ajax({
  ...
  data: form,
  ...
})

然后在Rails端,您可以通过params[:file_name](在控制器中)获得file_name

这是一个快速的建议,希望它将对您有所帮助。

干杯


非常感谢@kasperite建议使用FormData,这是此答案的重要组成部分。我将ajax调用更改为如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@action.bound uploadFile() {
  let form = new FormData();
  form.append("file", this.file);
  $.ajax({
    url: AppConstants.APIEndpoints.USERLOCATIONS + '/1/photos/1/upload',
    headers: {"Authorization": localStorage.getItem('authToken') },
    data: form,
    processData: false,
    contentType: false,
    type: 'POST',
    success: function (data) {
      alert(this.data.name +" uploaded successfully!");
    }
  });
}

然后将我的控制器更改为如下所示:

1
2
3
def upload
  @photo.upload_model(params[:file].original_filename, params[:file].tempfile)
end

params[:file].original_filename是文件名,而params[:file].tempfile是实际文件。

我的类方法现在看起来像这样:

1
2
3
4
5
6
7
8
9
10
11
def upload_model(original_filename, model_file)
  model = StorageBucket.files.new(
  key:"models/#{id}-#{original_filename}",
  body: model_file.read,
  public: true
  )

  model.save

  update_columns model_url: model.public_url
end