Wednesday, March 11th, 2009

Showing progress with the Safari 4 multiple file upload

Category: Browsers, JavaScript, PHP

<>p>Andrea Giammarchi has taken the new Safari 4 implementation of multi input file upload functionality and has written an article on how to write the client and server to enable this.

He shares the new XHR implementation:

javascript
< view plain text >
  1. var xhr = new XMLHttpRequest,
  2.     upload = xhr.upload;
  3. upload.onload = function(){
  4.     console.log("Data fully sent");
  5. };
  6. xhr.open("post", page, true);
  7. xhr.send(binaryData);

and the delves into a PHP server backend that groks things like X-File-Size and X-File-Name.

Then, he shows the client side code to push this all forward and packages it all up:

The external file with sendFile and sendMultipleFile function is in my repository and in the attached zip, while a workable example page with a limit of 1Mb for each file is here in my host.

Related Content:

Posted by Dion Almaer at 7:11 am
9 Comments

+++--
3.9 rating from 17 votes

9 Comments »

Comments feed TrackBack URI

Too bad the new File object don’t (yet) have three essential methods:

– getAsBinary()
– getAsText(encoding)
– getAsDataURL()

This way it could have been compatible with FF and, more important, would have allowed us to access uploaded files from the $_FILES array when using PHP on the server.

Comment by igstan — March 11, 2009

I can’t seem to find a way to split the ByteArray object or what ever the files collection contains. It would be very useful to be able to chunk uploads and possible pause/resume them. Google Gears has a nice implementation of this I ope Safari will adapt that concept.

Comment by Spocke — March 12, 2009

igstan, in FF we can use sendAsBinary and files[0].getAsBinary but you still need to use the php://input trick ’cause the super global $_FILES is not populated (also there is no way to set the file name)

FF3 currently supports my example with few adjustments, the problem is that so far total and loaded returns always an integer instead of real values.

the send method as HTML5 specs say should be able to send binary data and I think Safari did the right choice to manifest File instances as binary data when sent via xhr.send.

Finally, I think that getAsBinary method could not be that safe.
A malicious developers could parse and recognize files via JS and I guess it is a security issue (think about CSS attack over pages where people could send any kind of public or private file).

Something we had before with filesystem access via Internet Explorer, something they removed in latest versions of this browser and for security reason (both read and write). Would be nice to be able to have privileges to perform searches, reads, and writes, in a secure/private/local environment though … so let’s see if they will change this limitation.

Comment by WebReflection — March 12, 2009

@WebReflection, the $_FILES superglobal get populated if you know how to populate it. I wrote an extensive blog post about this which shows how to upload files using Ajax in FF3.

Ajax file upload in Firefox 3

The source code may also be found on github.

FF 3.5 will support Ajax progress events and I’m in the process of adding them to my Ajax uploader.

Last night I was trying to add Safari 4 support but to no avail due to those 3 missing methods.

Regarding the security issues. JavaScript cannot popup the file dialog, so there is no issue with malicious JavaScript reading local files, unless the user agrees this. The problem lies in the actions taken by the user.

Comment by igstan — March 12, 2009

igstan, with an XSS attack when user agrees I could read its file before he send them to the server. This is what I mean for security issue, an injected JS able to understand what the user is sending and to collect information or data somehow.
About the $_FILES super global, still about headers, what I meant is that there is no way to send the name as a normal post (in the send parameter, I thought you were talking about it).
At the same time I did not think at all about the boundary and the Content-Disposition so your post is an excellent hint to make the form even more degradable and easy to receive with or without JavaScript (via $_FILES or whatever way to receive the data).
Nice one, I’ll update my script asap, cheers.

Comment by WebReflection — March 12, 2009

P.S. igstan, you do not need getAsBinary if you send a file a time, which is fine for my example ;-)

Comment by WebReflection — March 12, 2009

@WebReflection, now I understand what you were saying about security. Well, I believe that is disputable as it’s not strictly a problem with the File object. It has more to do with the way that certain application was designed security wise. I agree though that a bad person would be very happy to be able to read some local files.

About the $_FILES super global, still about headers, what I meant is that there is no way to send the name as a normal post (in the send parameter, I thought you were talking about it).

Oh well, you could in FF3, but that data won’t be available in the $_FILES super global, but in the $_POST superglobal.

Please let me know if you are able to achieve in Safari 4 what I achieved in Firefox 3.

P.S. igstan, you do not need getAsBinary if you send a file a time, which is fine for my example ;-)

Your example is fine. Is just that I don’t want the server-side to have special cases for handling Ajax uploads. Not to mention that when you want to mix file uploads with ordinary POST data you might want to know the two are related when storing them in RDBMS or something. This implies additional logic on both the client and server. Anyway, as long as I remember client-side JavaScript had to deal with that kind of special cases…

Comment by igstan — March 12, 2009

@igstan, I agree that a special case does not make sense (requiring double logic on the server)
Mine was just an example about possibilities. Justin Mecham is doing over my example some truly interesting stuff, so as soon as I have time, I will try to merge his work with mine to create a gracefully enhanced multiple file upload for both Safari 4 and FireFox 3+
Actually I could implement something interesting for IE as well, let’s see if I’ll find time for a basic cross browser library

Comment by WebReflection — March 12, 2009

>> I will try to merge his work …
.. plus your suggestion about $_FILES ;-)

Comment by WebReflection — March 12, 2009

Leave a comment

You must be logged in to post a comment.