Upload BitmapData Snapshot to Server in AS3

Note : This class has been updated, you can view the new post here.

Here is a very simple wrapper class I wrote last night that allows you to take a BitmapData snapshot of a Display Object on the Stage, convert it to a .png or .jpg and upload it to your server in a directory you can specify at runtime. All in about 10 lines of code.

The technique is quite simple. You instantiate a new ‘DynamicBitmap’ and pass in the target DisplayObject you want to snapshot as well as a string of the filename you want to call it. e.g. ‘MyBitmapSnapshot.png’

In the following example I created two buttons on the stage which snapshot and upload the bitmap separately however you can combine this all into one action if you like.

private var _dbmp:DynamicBitmap;
private var _uploadScript:String = 'uploads/upload.php';
private var _uploadDirectory:String = 'images/'; // optional //
private var _target; // some display object on the stage //
private var _filename:String = 'myBitmapSnapshot.png';
 
public function ApplicationMain ()
{
     snapshot_btn.addEventListener(MouseEvent.CLICK, takeSnapshot);
     upload_btn.addEventListener(MouseEvent.CLICK, uploadSnapshot);
}
 
private function takeSnapshot(evt:MouseEvent):void
{
     _dbmp = new DynamicBitmap(_target, _filename);
}
 
private function uploadSnapshot(evt:MouseEvent):void
{
     _dbmp.upload(_uploadscript, _directory);
}

Underneath the _target DisplayObject is drawn into a BitmapData object and then based on the file extension you give it in the filename it is converted into either a JPEG or PNG byteArray using the AS3CoreLib encoding classes by Tinic Uro.

These encoding classes return a raw byteArray which by itself cannot be uploaded to the server as the MIME protocol requires precisely defined headers to accompany the raw image data and instruct the server what to do with it.

Enter the URLRequestWrapper class which is a slightly modified version of the UploadPostHelper class written by Jonathan Marston which adds in the necessary headers required by the server:

--pfhchaivbrmxhcighexxsspxpxhepeea
 
Content-Disposition: form-data; name="Filename"
 
myBitmapSnapshot.png
 
--pfhchaivbrmxhcighexxsspxpxhepeea
 
Content-Disposition: form-data; name="dir"
 
images/
 
--pfhchaivbrmxhcighexxsspxpxhepeea
 
Content-Disposition: form-data; name="Filedata"; filename="myBitmapSnapshot.png"
 
Content-Type: application/octet-stream
 
‰PNG

The URLRequestWrapper is simply a modified URLRequest with a data property that contains the image data and all the necessary headers required by the server, including the optional destination directory you specified for the image. When this URLRequest is loaded into a URLLoader object it arrives at the server via the global $_POST array.

I’ve included a simple upload script ‘uploads.php’ that looks for a ‘dir’ property in the header information which contains the _uploadDirectory variable you specified in Flash. It is entirely optional, if no directory is specified it will install the image in the default directory as specified in the upload.php script. This may prove handy in an application where the you’d like to be able to change the destination directory of the newly created image at runtime.

Note: If you specify a directory that does not exist on the server it will be created via the new recursive flag introduced in php5. Be sure to have php5 installed and enabled on your server or the script will throw an argument error and possibly not run.

Source Example Files Here

  • Grant

    Out of all the tutorials and source files out there on how to do this yours was the only one for me that worked straight away. So thanks very much! Can I use this source code freely in my own projects?

  • Stephen Braitsch

    Absolutely. All code included is open source and available under a BSD license. Enjoy.

  • Marvin

    This has been the most educational AS experience for me ever. Thanks for this! I seem to have everything working properly, but is there a way to get rid of the border around the .png files?

  • http://www.thermosis.com/ Jayden Lawson

    This is great. Is there anything similar for AS2?

  • http://www.faustocarrera.com.ar Fausto Carrera

    For AS2 there’s the Quasimodo class:
    http://www.quasimondo.com/archives/000645.php#000645

    I’ts there a way to calculate the percent of PNG/JPG exportation?

  • Kris

    Awesome, thanks a lot! :)

  • http://blog.richardolsson.se Richard Olsson

    This works great and I got a chance to use it in production right away. I’m a bit disappointed by the way it’s laid out, API-wise, though, which makes it, while easy to use, also very narrow. But at least it’s an awesome POC!

    I might refine the interface and get back to you. (Although for this project I will probably just hack to change file format encoding et c.) Thanks a lot for sharing the code for this method!

  • http://www.behzad.se Bezz

    Hi
    I have a question. I was looking for a way to send some variables to the PHP file at the same time. I mean like a HTML form which uploads the file and sends the value of fields at the same time.

    Is there a way to do that?
    thanks

  • Stephen Braitsch

    @Richard. Indeed code can always be improved upon. If you rewrite this and post a more feature rich version, please share the link.

    @Bezz, while this is possible I would encourage you to make a separate call to the server with your form data as you will most likely want to receive some message back from the server after that form data has been processed. By adding it to the data property of the request that contains the encoded image data you may run into decoding problems on the server.

  • Bezz

    Hi everyone
    I’ve made a flash project which is almost complete. The only thing I need to do is to upload a snapshot of a display object. It seems that this script works but I don’t know how to use it.
    I will really appreciate if someone tells me how to do it. I mean how to configure my project to import this class file.

    When the project gets to this line:
    _dbmp = new DynamicBitmap(_target, _filename);

    It generates an error:
    1080: Call to a possibly undifined method DinamicBitmap

    Here is my E-mail in case someone can help me
    behzad1122@hotmail.com

    Thanks

  • David

    I second Bezz’s last comment: What version of Flex has a DynamicBitmap class? I don’t see it here, in Flex 3 documentation:
    http://livedocs.adobe.com/flex/3/langref/all-index-D.html


    Oh, nevermind, I see it in the source example: it’s a custom class that extends Sprite.
    k thanks!

  • Jason

    Hey thanks for this :)

    Just a note that on this page my computer was lagging up. Firefox used 485MB of RAM with no other tabs open. Restarted my comp, same thing. Tried IE6 (God forbid!), again no other pages open, and it jumped up to 1.1GB of RAM. Kind of scary.

    This has happenned on WindowsXP and Linux (Ubuntu 8.04), using Firefox 3, IE6, Opera and Chrome.

    As for what might be causing it, IE6 reported an error in this javascript file:
    http://include.reinvigorate.net/re_.js

    But Chrome has a task manager that keeps track of how much each plugin is using – and a flash plugin was using 480MB

    Anyway, just thought I’d note. I’ve visited this page before and had no issues but I thought it worth reporting. Again, thanks for the help with Actionscript :)

  • Stephen Braitsch

    Thanks Jason for the note.

    I recently installed a lightbox plugin that was doing some funky things on the page and removing that seemed to improve page performance. I appreciate the heads up and will take a closer look. Cheers :)

  • harry

    I can’t download the source code, there was a problem, can anyone help me ?

  • http://evensimon.com Simon

    Hey,

    been working with this script and ran into a problem, perhaps you could give me some advise… The script is working fine when I run it from my PC (on Flash CS3), but when I upload it to the server, nothing happens, no request is going to PHP script… :/ I thought it might be some kind of security error in the URLRequest but couldn’t find anything…

    Thanks,
    Simon

  • Philipp

    Hi Stephen,

    “Absolutely. All code included is open source and available under a BSD license. Enjoy.”

    Unfortunately I don’t believe that’s the case. Jonathan Marston licensed the class on which you’re building under a CC non-commercial attribution sharealike license.
    To my understanding, this means any derivative work (i.e. software that uses this – and by extension your – code) needs to be licensed under CC itself and may not be of commercial nature.

    So it doesn’t look like we can use this freely in our own projects. Which is a pity because it would be just what I need right now.

  • Philipp

    I’d like to add to my previous comment that I’ve since contacted Jonathan and he kindly gave us permission to use his class under an MIT license.
    But yes, if you’d like to use this in your commercial projects and want to be on the safe side, you’ll need to contact him.

  • Stephen Braitsch

    Thanks Philipp for your comments. For the record any code that I write and make available on this site is completely free to use in your personal or commercial projects.

  • Corey

    Would this also work from an AIR app, or could it be modified to work in one?

  • http://www.dannophotography.com danno

    but doesn’t this hang when trying to export a large stage or MC size ( like 2000px x 2000px ) ?

    rocksteady,
    danno~

  • devo

    “been working with this script and ran into a problem, perhaps you could give me some advise… The script is working fine when I run it from my PC (on Flash CS3), but when I upload it to the server, nothing happens, no request is going to PHP script… :/ I thought it might be some kind of security error in the URLRequest but couldn’t find anything…”

    I have the exact same problem. I’ve tried adding the path to the php file as both relative and absolute, still I cannot get images to write to the server when the swf runs outside of the flash ide. Please help.

  • http://www.runtime.co.za RW

    Security violation issues sorted out by removing custom headers line 120 in URLRequestWrapper.as (_request.requestHeaders.push( new URLRequestHeader( ‘Cache-Control’, ‘no-cache’ ) );) Please advise id this is a NO NO.. :) , but it did the trick for me. Prop got to do with custom headers not being allowed anymore. please correct me if i am wrong.. appreciate the code..

  • eddiem

    hi ive got a question?

    im doing a drag and drop function in AS2 u can view
    it on art.tafe.vu.edu.au/dgalletta/eddie/index.html on the build a t shirt page .

    my question is how do i save an image once im happy with the design
    and by the way the objects are buttons…can anyone help?

  • Andy

    Is there a way to make this work if you don’t have PHP 5 installed? My server only have PHP 4.3.9, but would still like to use this.

  • http://davidwaclo.com dave

    First off this is awesome! I would like to have an application that produces a chart and then has the option of emailing that image. I’d like to send the image as an attachment, but with this I could send an email that linked to the image I create on the server.

    My question is would it be possible to modify this so that the image was sent directly as an attachment?

    thanks!

  • Stephen Braitsch

    @Andy if you remove the third parameter (recursive flag=true) in the call to mkdir($dir, 0777, true); it should run on php4.

    @Dave sure you could wait for the response from the server that the image upload was successful and then call another php script that generates an email passing to it the url of the image you just created. Your email generating script could use that image url to create the attachment.

    I suggest grabbing the updated source for this feature from my more recent post here.

  • Sundev

    It seems like the latest update to Safari on Mac made this break. But, I tweaked it to send the directory being uploaded to as a GET variable appended to the url, deleted the unneeded code in the URLRequestWrapper and that worked.

  • kanyal

    HI
    this is working when uploading from local pc but not working when i try it in facebook or other server. when try to upload created snapshot there is no effect no url in status bar to show that request is going to server and just held there.
    what can be problem when swf is running from server. can any body help to resolve this issue.
    thanks in advance

  • Jay

    trap and display your security errors you will find that is your problem.
    flash 10 security model has some funny results when you manipulate images across different domains

  • tom

    Hi,

    i’ve been using this in cms system for 18 months, now i’m updating for a new version of the site and it won’t work. i’m pretty sure it’s the stuff to do with the POST headers set by URLRequestWrapper but i get no security errors nor do ANY of the events fire, it just fails silently once DynamicBitmap.upload is called.

    any ideas what might be going on?

  • http://inkstudio.be Wellens Ludovic

    I’m in the same situation than Tom, does anybody have a solution?

  • gricceri

    I don’t know if this can help someone, but I got flash didn’t executing the request while in fullscreen mode on mac. Toggled from the fullscreen to normal mode and everything worked again.

  • http://style-review.com landed

    This is a tidy little script, just wanted to know how we might send the form data separately and keep the image associated with that data ? I see that there is a spot for form data if im not mistaken

    _dbmp.upload(_uploadScript, _uploadDirectory,{var1:”test”});

    not sure how I read that I guess its just available as post variables. You mention that this may give problems earlier to send the form and image together. Again, how is ok to send separately and the association is not lost (busy server many images getting uploaded at once scenario) …

  • Stephen Braitsch

    It’s been awhile but you should be able to pass in an object of name/value pairs as the third arg to the upload method and then retrieve those values from the POST array on the server side.

    For example:
    _dbmp.upload(_uploadScript, _uploadDirectory,{var1:”test”});
    Should generate a ‘var1′ prop in the POST array:
    echo $_POST['var1'] = ‘test’.

  • moname

    had the same problem as Tom and Wellens. Fixed it by replacing the following line:
    _request.contentType = ‘multipart/form-data; boundary=’ + _boundary;

    with this one:
    _request.requestHeaders.push(new URLRequestHeader(‘Content-Type’, ‘multipart/form-data; boundary=’ + _boundary));

  • http://www.pr-creative.com Phil Roberts

    Hi Stephen,
    This is going to save my bacon!!!! (Hopefully!)
    I need to save an image of this drag and drop flash movieclip:

    http://www.softplay-direct.com/play-pods/design-your-own-layout.html

    As you can see you just make your own design but when done I need to be able to capture the image with the design layout.

    I have Flash 8 pro and the files supplied through your links will not open.
    any help with the .fla or even is this possible with Flash8 pro
    thanks
    Phil

  • http://nikohelle.net Niko Helle
  • mp

    I am trying to replicate your application but get this error being thrown from line 139 of JPGEncoder.as

    1046: Type was not found or was not a compile-time constant: BitString.

  • Stephen Braitsch

    @MP BitString.as is in the adobe/images package so make sure your import path is correct. Either way though consider using the updated version of this class found here : http://www.quietless.com/kitchen/save-an-image-from-flash-to-the-desktop-or-server/

  • http://www.behzad.se hemsida

    Great article. It helped me alot
    Thanks for sharing

  • James Burrows

    Yeah, can confirm that NONAME’s solution worked for me to fix silent failure issue when used in a browser environment.

  • Piti

    Awesome app and tutorial.
    Thanks for sharing.

  • Gordon

    sorry guys, I’m an idiot. I had “http://” in the save path and you can’t write like that over http. I also was thinking backwards not realizing to what that path is relative to. Changing the _saveFileName to “../../recordings” sorted me out : ]

  • FlappRulz

    Great work, i can see you really know your stuff. You just saved me a lot of work, thanks a lot!

  • venu

    HI
    this article i am using working well
    But image is creating with out the name,

    I want to upload image with the name plz help me.