Send / Receive javascript FileList to rails 7 controller (Drag and Drop mode)

32 Views Asked by At

I have a form.

<form id="add_content" enctype="multipart/form-data" action="/contents/create" accept-charset="UTF-8" method="post"><input type="hidden" name="authenticity_token" value="*****" autocomplete="off" />
    <input type="hidden" value="*****" id="database_id" name="database_id">
    <div id="drop-area">
        <input type="file" id="file_list" name="file_list" multiple>
    </div>
</form>

I have some javascript to add drop event and handle all.

let dropArea = document.getElementById('drop-area')

dropArea.addEventListener('drop', handleDrop, false)

function handleDrop(e) {
    let dt    = e.dataTransfer
    let files = dt.files

    handleFiles(files)
}

function handleFiles(files) {

    let form = document.getElementById('add_content')
    console.log(files)
    let file_list = document.getElementById('file_list')
    console.log(file_list.files.length)
    form.submit();
}

I drag and drop some (two) files I can see a FileList into console.


FileList {0: File, 1: File, length: 2}
  0: File {name: 'kk.wav', lastModified: 1671550812159, lastModifiedDate: Tue Dec 20 2022 16:40:12 GMT+0100 (Central European Standard Time), webkitRelativePath: '', size: 832216, …}
  1: File {name: 'kk.marcos.wav', lastModified: 1671550812023, lastModifiedDate: Tue Dec 20 2022 16:40:12 GMT+0100 (Central European Standard Time), webkitRelativePath: '', size: 1147470, …}
  length: 2
  [[Prototype]]: FileList

But console.log(file_list.files.length) write '0' on console

After submit the form, the Payload look like this.

authenticity_token: *****
database_id: *****
file_list: (binary)

But in my controller file_list is nil

  def create
    database_id = params[:database_id]
    file_list   = params[:file_list]

    puts "================================================================="
    puts file_list.class
    puts "================================================================="
App 1686102 output: =================================================================
App 1686102 output: NilClass
App 1686102 output: =================================================================

Then, I add some code to my javascript function handleFiles to add the FileList to my input type file

function handleFiles(files) {

    let form = document.getElementById('add_content')
    console.log(files)
    let file_list = document.getElementById('file_list')
    // Add FileList to the input type file
    file_list.files = files
    console.log(file_list.files.length)
    form.submit();
}

Now console.log(file_list.files.length) write '2' (this is fine) and now the controller receive a file, but just one file (the last one). Not two.

App 1686102 output: =================================================================
App 1686102 output: ActionDispatch::Http::UploadedFile
App 1686102 output: =================================================================

If I try to get files_list.length in the controller I get

undefined method `length' for #<ActionDispatch::Http::UploadedFile:0x00007f356c0dd1c8 @tempfile=#<Tempfile: (closed)>, @content_type="audio/wav", @original_filename="kk.marcos.wav", @headers="Content-Disposition: form-data; name=\"file_list\"; filename=\"kk.marcos.wav\"\r\nContent-Type: audio/wav\r\n">

What would be the proper way to send o receive more than one files?

1

There are 1 best solutions below

0
icalvete On

Well, is as easy as change the name of the input file.

<input type="file" id="file_list[]" name="file_list[]" multiple>

instead of

<input type="file" id="file_list" name="file_list" multiple>

Thanks to Rails: Multiple Fileupload is missing all files but one

Maybe mine is duplicated.