During my last project I faced a problem to upload multipart/form-data to server using Flash. I need to do it using ActionScript only. The idea was to send to server an image generated in flash and several variables but all this data had to be POST.
I found several projects that were using Flash Socket to send multipart requests to server but the problem was that sockets required custom server configuration to work. As you understand we cant ask remote service to reconfigure their system only because we need it.
So the only way was to build your own custom URLLoader class (not socket) to send multipart form data. Ok, no more words (I hate all this typings) here is simple but usefull (as I think) MultipartURLLoader class. You will find source and small samples with php script inside.
Unfortunately there is a problem getting progress event. We cant show any progress during sending data to server because flash doesnt support it. (the same problem with sockets)
LATEST VERSION UPLOADED TO GOOGLE CODE
UPDATES:
version 1.1
- Added options for MIME-types (default is application/octet-stream)
version 1.2
- Added clearVariables and clearFiles methods
- Small code refactoring
- Public methods documentaion
in short we can add variables and files to loader class:
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 29 | import flash.utils.ByteArray; import ru.inspirit.net.MultipartURLLoader; var data1:ByteArray = new ByteArray(); data1.writeUTFBytes("This is a test 1"); data1.position = 0; var data2:ByteArray = new ByteArray(); data2.writeUTFBytes("This is a test 2"); data2.position = 0; var ml:MultipartURLLoader = new MultipartURLLoader(); ml.addEventListener(Event.COMPLETE, onReady); function onReady(e:Event):void { // Upload Complete } // simple string data ml.addVariable('test', 'test variable'); // file data: ByteArray, File name, Name of the file field, content MIME type (default application/octet-stream) // use [] if you need identical file field name // specify MIME type for your file part ml.addFile(data1, 'test1.txt', 'Filedata[]'); ml.addFile(data2, 'test2.txt', 'Filedata[]', 'text/plain'); ml.load('test.php'); |


Wow, nice work!
MarstonStudio wrote a similar class for multipart data in AS3 without sockets, but he only sends one file and one object.
I was looking to modify the class, but your class is perfect! Thanks
Hi! Nice work, thx! Just a remark: i cant catch any event from it…
@zlatko
can you be more specified in your problem? what you send and what is your receive script?
@Eugene
Yep, sure
Also i try to set breakpoint into MultipartURLLoader.onComplete(), but never reached it..
Hm…Maiby “image/jpeg” damage it?
@zlatko
and what about your server script? it returns anything? As far as i know u should return anything so flash will see that everythink is ok. simple
echo ‘ok’;
is enough
also have u tried not to use content type? and use default one?
@Eugene
Yes, server script return some text. Also i try to use default header but nothing change… On server side we use nginx. Maiby it binded with that problem…
Thats strange I cant test it on nginx. But eveything is ok on my server. it sends data and fires Complete event…
@Eugene
I clear that by changing value of ‘useWeakReference’ param on false in addEvenetListener for Event.COMPLETE.
@zlatko
Thanx for posting that! I’ve updated my svn repo setting useWeakReference to false.
the latest version currently on my google code repo.
@Eugene
Sounds good
It will be greate to see in future release some alike async upload, becouse now, if i want to send big file my environment go into sleep mode
@zlatko
but this class was designed to mirror web forms posting method. so the feature of partly uploading is required custom server side specially done for this class.
yep. huge file uploading is a problem.
Thanks for the handy class Eugene.
2 things I noticed:
You have urlRequest.requestHeaders.push( new URLRequestHeader( ‘Cache-Control’, ‘no-cache’ ) ); but I don’t believe this is necessary as it is a POST request. This was causing an issue for me as the swf doesn’t reside on the same server as the script and I was receiving:
Error #2044: Unhandled securityError:. text=Error #2170: Security sandbox violation: http://domain1/swf.swf cannot send HTTP headers to http://domain2.com/script.php.
This can be resolved by adding a variation of to the crossdomain.xml file but it was easier for me to comment out that line.
2. It doesn’t seam possible to configure the returned dataFormat or even get the server response with the current MultipartURLLoader. I think this class should extend URLLoader directly so that these things are accessible.
Thanks,
Mark
@Eugene
Hi! I mean some async preparing file for sending… I have sleep mode in that part, actually in getFilePartData() method…When file is huge there is long cycle that freeze my FlashPlayer….
p.s. sorry for my poor English
p.p.s. могу по русски поробовать
ага) по русски лучше конечно!)
я тебя понял. это решит проблему с недоступностью флэша. Но я так понимаю что когда ты кодируешь этот кусок ByteArray который ты потом передаешь лоадеру у тебя тоже должно все подвисать. Ты же его как-то создаешь прежде чем отдать на загрузку? Обычно это случается при генерации большой картинки в PNG например.
Хе хе) не подвисает потому что юзаю что-то типа етого: http://www.switchonthecode.com/tutorials/flex-tutorial-an-asynchronous-jpeg-encoder
Тоисть асинхронный энкодер..было бы круто повторить в твоем класе
Thanx, Mark
I’m going to rewrite class to add async data object generation with progress event dispatching while building request. It will help avoid freezing flash player while generating huge file requests. Also I’ll remove ‘Cache-Control’ header.
and I’ll think about configuring returned data…
Wow, you rock!
You class just saved me lots of troubles…
Many thanks!
Hi! Nice work, thx!
I retrieve the server response doing this:
Thank you very much for this!
Your work saved my life (or at least made it substantially easier
You are welcome!
Awesome! Its special solution for my problem. Thanks!
In Flash 10 I get an error: SecurityError: Error #2176
Thanks muchly for this – I’m trying to use it to upload files with a Content-Type of something other than the default application octet stream.
I’ve added a couple of lines to the code, to make the class dispatch a DataEvent with the server response, just like the FileReference.upload class would;
private function onComplete( event: Event ): void
{
removeListener();
dispatchEvent( event );
dispatchEvent(new DataEvent(DataEvent.UPLOAD_COMPLETE_DATA, event.bubbles, event.cancelable, loader.data));
}
omg! Thank you VERY MUCH for posting this.
Every example of sending jpgs to a server never used URLVariables (they always just used URLLoader and set the data property to be the jpg byte array directly) so I was having the hardest time sending user login info along with the image.
But I used yours and it worked like a charm! Thanks again.
Tmz: Flash Player 10 change the security policy and you have to call the MultipartURLLoader class following user’s interaction such as mouse or keyboard event. So you need to make a call like so:
thanks you save me! I was unable to use multipartLoader class. But your MultipartURLLoader rocks!!! Really thanks again!
This was exceedingly helpful, thank you!
This was really helpful, it saves us some headaches!
Hi all,
I corrected a POST problem with Python HTTP server. This patch is :
private function closeDataObject(postData:ByteArray):ByteArray
{
postData = BOUNDARY(postData);
postData = DOUBLEDASH(postData);
// START CORRECTION
postData = LINEBREAK(postData);
// END CORRECTION
return postData;
}
I know I’m probably just doing something wrong…When I test in Flash CS4 it sends off to the URL (running Apache on localhost) and processes just fine. However when I export the movie and run it through my web browser (on localhost) it doesn’t try to load. I get no io error, no http status code, no security error, nothing. And of course it doesn’t complete. Do the events fire for security issues and such? It’s really odd that it works within Flash CS4 but not embedded on the page…Bummer. And I have a crossdomain.xml which I wouldn’t think I’d need anyway on localhost but..
Hello
I am building a large video uploader and looking ito flash options to do this with resume capabilities… any chance doing that with your class?
I know I need php work server side, but how can I read only partial file in flash and send it?
Thanks
Cris Rus
I think there’s a major security issue with Flash and it may only be possible to submit with an actual button within the flash movie… One of my issues was trying to submit via ExternalInterface. I wanted javascript to send the form. It had problems with that.
Bringing the button into the flash I STILL have issues when on http://localhost … When testing from within Flash (test movie) it seems to work. That appears to be the only time it works.
Is there something silly and basic I’m missing?
Turns out security issue. The POST has to be made with a click event from within the Flash (IF and ONLY if you’re attaching an image, you can use this multi loader with just strings being passed with no problem via externalinterface). Or in other words, the “submit” button has to be in Flash. I was hoping to call it from ExternalInterface/Javascript. Adobe’s recent security change prevents that.
Does anyone know if there is any way around this?
I want to put a flash “browse for file” field that mimics a normal html form element up somewhere in the page, and then a normal submit button (javascript on the click, not 100% normal html form element submit button) down the page further after some other form fields. If the button has to be in Flash that really limits my layout abilities.
Even if there is a server side tweak to be made…Anything??
Tom: have you tried with an element in the element in
your crossdomain.xml file?
Tom: have you tried with an <allow-http-request-headers-from
domain="*"/> element in the <cross-domain-policy> element in
your crossdomain.xml file?
I actually had an outdated version of this class. There was a very simple fix. Funny that I read so many other blogs/sites and they also had similar problems (different classes and such). Strange, but glad it worked out. Thanks for the suggestions. I ended up not needing a crossdomain.xml at all actually.
Also wish someone could explain one of the two different approaches above to get the response from the server….Both snippets of code just seem worthless to me right now, trying everything. A tiny bit of help and explanation maybe?
Ahh…. loader should be _loader.
So the above does work (and I think a great small addition to the class):
dispatchEvent(new DataEvent(DataEvent.UPLOAD_COMPLETE_DATA, event.bubbles, event.cancelable, _loader.data));
Thanks for this work. It is very cool and works great! For the file attachment I am writing data to a ByteArray and then when it was ready, I make the multipart.addFile(..) call. What I would really like to do is incrementally add the data to the Byetarray (or some other structure), and have MultipartURLLoader chunk transfer encode the request to the server as data is fed to it. Any hints on how to accomplish this? Would this be a difficult project to add this sort of capability?
Tom, you mentioned you found an easy fix to your problem but you didn’t mention what it was? I’m having a similar issue right now that I’d love to get around. I have a profanity filter happening on my form submission, and after it comes back successfully, I continue on with the multi-part post. Unfortunately, due to the intervening asynchronous call, flash is throwing that pesky security error.
Thanx man! You are awesome!
You solved the problem that I tryed to solve for several hours but with no success.
Hi,when I export the movie and run it through my web browser (on localhost) …nothing,
with swf works .Why please?
Nice work, i wanted to write itself, since i have found i will use your class =)
Hi Eugene,
How can we set cookies to the multi part request.
I am able to upload the file, but my server does authentication based on cookie being sent.
Please help.
Thanks in advance
Ganesh