Maverick
Maverick

Reputation: 2016

Assign file as value of hidden input

I am using a multiple file upload field <input name="filesToUpload" id="filesToUpload" type="file" multiple /> in my app.

What I want to accomplish is to list the files the users chose and than allow them to delete any of them in the list. At the end, when the form is submitted, I send the whole data via AJAX, as binary, using the FormData object.

It all works great, except for the delete part.

I know that the FileList attribute is read-only, so what I did was to distribute the files as values of hidden input fields, appended to each of the li where I list the file names. So if the user removes a li item, the hidden input field is gone with it, and at the end, I collect all remaining by appending them to the FormData object.

Problem is, every attempt I made to assign the files as values to the hidden inputs gave me weird results.

My code is something like this:

listFiles : function () {
    var file, files, filesList, filesLength, read;

    files = this.files;
    filesList = $('.files');
    filesLength = files.length;

    // Clear the list
    filesList.html('');

    for ( var i = 0; i < filesLength; i++ ) {
        file = files[i];

        // This is to read the content of the file
        read=new FileReader();
        read.readAsBinaryString( file );

        // When reading is finished
        read.onloadend = function() {
           filesList.append(
                    '<li>' + 
                    '<span class="fileName">' + file.name + '</span>' + 
                    '<a href="#" class="deleteAttachment">x</a>' +
                    '<input type="hidden" name="file[]" value="' + read.result +'"/>' +
                    '</li>');
         }
     }
  }

I just get the data from the last file, also, the DOM is broken since the data gets printed all over the place.

Demo here => http://jsfiddle.net/zKyXC/

Upvotes: 2

Views: 8461

Answers (2)

Maverick
Maverick

Reputation: 2016

I have tried various ways to implement the method described above ( assign each separate file to the value of an input[type="hidden"] field in order to allow file delete functionality ) but non of them were successful. At this moment, I do not know if this is this possible to be done at all.

However, I did manege to solve the problem with an alternative solution. Here it is in case someone else finds it useful.

Instead of using input[type="hidden"] I used a global array where I stored the files upon receiving them. Then I remove items from that array the standard way you would remove objects from an array. At the end I append each item to the formData object and send it to the server.

I create and fill the global array like this:

globals.files =[].slice.call( this.files ); 

i remove from it like this:

$.each( files, function( index, val ) {
            if ( this.name === fileText ) {
                globals.files.splice( index, 1 );
            }
        });

Note : fileText is where I store the name of the item to be deleted.

And at the end I append it to formData :

var formData = new FormData();

$.each( files, function( ind, val ) {
            formData.append( 'files[]', this );
       });

And send this as the data property of a standard jQuery ajax call.

Upvotes: 3

S.831
S.831

Reputation: 123

if I am not wrong, only file with quotation mark " goes wrong, if you do not escape it, value will be cut off at the first occurence of " and the rest part will be shown as html, so what you need is

read.result.replace(/"/g, '&quot;');

Upvotes: 0

Related Questions