FileReader icon indicating copy to clipboard operation
FileReader copied to clipboard

Question: Any upload examples?

Open McGern opened this issue 11 years ago • 12 comments

Hi,

Have been looking at using this polyfill solution for ie9 and below, but lack the knowledge to plug this into something that will upload the files once they are chosen. I can get the filelist fine, the documentation was no problem there, but I have been searching for a while now for a working method to then upload the files in the list to the server. I have a working upload api, but just don't know how to plug the client side in.

Any further documentation would in the readme would be greatly beneficial.

Thanks, J

McGern avatar Oct 02 '12 22:10 McGern

In fact this is a file reader plugin, not a file upload plugin! It's goal is to allow you to read and process files in browsers that don't support it yet. If you then want to upload this data, just send an XMLHttpRequest POST or PUT with it in content.

AVapps avatar Oct 06 '12 11:10 AVapps

Thanks for the reply. Sorry, but I must not have been clear enough in my first post. I can successfully read a file and use the API to produce a preview image, but I am having trouble formulating the code to upload the files. I have a side-by-side test using a native file input and a swf filereader (using chrome for test). Testing both, shows that I can read multiple files and get the FileList object, but when I try a basic upload using this code (subset)

function uploadFiles(e) { var files = e.target.files || this.files; for( var f = 0; f < files.length; f++) { $.ajax({ url: "/Property/UploadPhoto/1", data: files[f], type: "POST", processData:false }); } }

The native version works and uploads the file and I can see the image. The swf version also uploads the file, but the data stream doesn't have any data in it so the image isn't correctly created (also tried a PUT with the same results). I was hoping to use this as a patch for IE8 and IE9, but can't find documentation or examples that support this method. Most tutorials assume the usage of the native html5 FileReader, therefore also assume the browser supports xhr.upload (for example).

Just a little lost in the next step of, as you put it, "just send an XMLHttpRequest POST or PUT with it in content". A little bit of script in the documentation would be very much appreciated as this plugin is really only for those users who wish to support IE,

Thanks very much for the time and effort that you and others put into this plugin. J

McGern avatar Oct 08 '12 21:10 McGern

Please try again setting 'contentType' to 'application/json' in $.ajax options. Did you check that "files[f]" is not empty?

AVapps avatar Oct 24 '12 13:10 AVapps

Hi, thanks for getting back to me.

Put in the contentType : 'application/json', but then got a error from the server about invalid json primitive (.net mvc v4). I tried removing the processData bit, but then jquery complained about illegal input.

For both cases (with and without the contentType), I looked the at request headers for the post in Fiddler and the content-length for my test file (using native filereader) was e.g. 12774, but using the flash shim the content-length was only 15.

The file object in the loop is available. If I interrogate the object "size" property, they both version show the same size e.g. 12774.

I am seem to be missing an integral step and any help would be appreciated.

Thanks again, Jarrod

McGern avatar Oct 26 '12 16:10 McGern

Hi, is there any available info yet on how to use the content and xmlhttprequest to upload the file? I cannot find any examples of doing this.

Thanks.

McGern avatar Mar 11 '13 14:03 McGern

You may have to manually generate a multipart form request, as described here http://igstan.ro/posts/2009-01-11-ajax-file-upload-with-pure-javascript.html unless somebody wrote a polyfill for FormData object.

glebm avatar Mar 30 '13 02:03 glebm

Looks like there is a polyfill here https://github.com/francois2metz/html5-formdata

glebm avatar Mar 30 '13 02:03 glebm

The main problem I'm running into is that I can't upload the file object this polyfill gives you. It isn't an actual File object and I believe it isn't qualified to be uploaded as a result (can someone prove me wrong?)

Here's the working ajax-based file upload code I'm using (code from http://quickleft.com/blog/how-to-upload-to-carrierwave-with-javascript):

formData = new FormData()
formData.append "user[avatar]", file

$.ajax
  url: "/api/v1/user"
  data: formData
  headers: { 'X-CSRF-Token': App.csrfToken }
  cache: false
  contentType: false
  processData: false
  type: 'PUT'

Now a normal File object (provided by the input type="file" element) works beautifully with this. Here's what my rails server sees:

(rdb:205) p params[:user]
{"avatar"=>#<ActionDispatch::Http::UploadedFile:0x00000110a741d8 @original_filename="22429_10100746190011218_763412277_n.jpg", @content_type="image/jpeg", @headers="Content-Disposition: form-data; name=\"user[avatar]\"; filename=\"22429_10100746190011218_763412277_n.jpg\"\r\nContent-Type: image/jpeg\r\n", @tempfile=#<File:/tmp/RackMultipart20130729-5382-nfgmv3>>}

Now watch what happens when you try and send this polyfill's file object instead:

(rdb:384) p params[:user]
{"avatar"=>"[object Object]"}
(rdb:384) p params[:user][:avatar].class
String
(rdb:384) p params[:user][:avatar]
"[object Object]"

john-bai avatar Jul 29 '13 20:07 john-bai

I ended up using moxie instead

glebm avatar Jul 29 '13 22:07 glebm

I thought about converting the result of the readAsDataURL(file) call to a Blob which can be appended to the FormData passed (proposed at http://stackoverflow.com/questions/4998908/convert-data-uri-to-file-then-append-to-formdata), but I'm not able to decode the readAsDataURL result using window.atob()

Any thoughts about why I'm unable to convert the file data URI using window.atob()?

byteString = atob(dataURI.split(',')[1])
INVALID_CHARACTER_ERR: DOM Exception 5: An invalid or illegal character was specified, such as in an XML name.

john-bai avatar Jul 30 '13 00:07 john-bai

Found the problem and a SOLUTION. Looks like the newlines in the base64 encoding were the invalid/illegal characters. window.atob() doesn't seem to support them, so I added a line of code to strip the newlines from the base64 encoded data:

dataURI = dataURI.replace(/(\r\n|\n|\r)/gm,"")
byteString = atob(dataURI.split(',')[1])

I think I'll have a working upload example soon!

john-bai avatar Jul 30 '13 01:07 john-bai

So I ended up getting the file upload working by sending the base64 encoded data of the file to my server. My original effort to follow http://stackoverflow.com/questions/4998908/convert-data-uri-to-file-then-append-to-formdata wasn't practical because Safari 5.1.9- doesn't support any Blob object creation.

You'll have to add code server-side to decode the base64 encoded file, but the file upload will work in that case. If using ajax, pass it to your server as an attribute of your JSON or XML representation. If a plain form, use a hidden input element and set its value to the base64 encoded file data.

john-bai avatar Jul 30 '13 04:07 john-bai