Upload ByteArray to Flickr

If you’ve used the the AS3 Flickr Library for uploading images to Flickr you know that it requires a FileReference object. Since you can only get a FileReference if you ask the user to browse to a local image on their hard drive or if you’re using AIR and just grab an image from the user’s hard drive. But what if you just want to upload a dynamically generated image from within your SWF?

With the help of an open-source MultipartURLLoader class, I went in and added the ability to upload a bytearray to AS3 Flickr Library. Just add the following method to the Upload 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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
public function uploadBytes(photoData:ByteArray,
				title:String = "",
				description:String = "",
				tags:String = "",
				is_public:Boolean = false,
				is_friend:Boolean = false,
				is_family:Boolean = false,
				safety_level:int = 0,
				content_type:int = 0,
				hidden:Boolean = false) : Boolean {
 
	// Bail out if missing the necessary authentication parameters
	if (_service.api_key == "" || _service.secret == "" || _service.token == "") {
		return false;
	}
 
	// Bail out if application doesn't have authorisation to writ or delete from account
	if (_service.permission != AuthPerm.WRITE && _service.permission != AuthPerm.DELETE) {
	    return false;
	}
 
	// The upload method requires signing, so go through
	// the signature process
 
	// Flash sends both the 'Filename' and the 'Upload' values
	// in the body of the POST request, so these are needed for the signature
	// as well, otherwise Flickr returns a error code 96 'invalid signature'
	var sig:String = StringUtil.trim( _service.secret );
	sig += "FilenamePhoto";
	sig += "UploadSubmit Query";
	sig += "api_key" + StringUtil.trim( _service.api_key );
	sig += "auth_token" + StringUtil.trim( _service.token );
 
	// optional values, in alphabetical order as required
	if ( content_type != ContentType.DEFAULT ) sig += "content_type" + content_type;
	if ( description != "" ) sig += "description" + description;
	if ( hidden ) sig += "hidden" + ( hidden ? 1 : 0 );
	if ( is_family ) sig += "is_family" + ( is_family ? 1 : 0 );
	if ( is_friend ) sig += "is_friend" + ( is_friend ? 1 : 0 );
	if ( is_public ) sig += "is_public" + ( is_public ? 1 : 0 );
	if ( safety_level != SafetyLevel.DEFAULT ) sig += "safety_level" + safety_level;
	if ( tags != "" ) sig += "tags" + tags;
	if ( title != "" ) sig += "title" + title;
 
	// Create MultipartURLLoader to send upload
	var loader:MultipartURLLoader = new MultipartURLLoader();
	loader.addFile(photoData, "Photo", "photo");
	loader.addVariable("auth_token", StringUtil.trim(_service.token));
	loader.addVariable("api_sig", MD5.hash(sig));
	loader.addVariable("api_key", StringUtil.trim(_service.api_key));
 
	if(content_type != ContentType.DEFAULT) loader.addVariable("content_type", content_type);
	if(description != "") loader.addVariable("description", description);
	if(hidden) loader.addVariable("hidden", hidden ? 1 : 0);
	if(is_family) loader.addVariable("is_family", is_family ? 1 : 0);
	if(is_friend) loader.addVariable("is_friend", is_friend ? 1 : 0);
	if(is_public) loader.addVariable("is_public", is_public ? 1 : 0);
	if(safety_level != SafetyLevel.DEFAULT) loader.addVariable("safety_level", safety_level);
	if(tags != "") loader.addVariable("tags", tags);
	if(title != "") loader.addVariable("title", title);
 
	loader.addVariable("description", description);
	loader.addVariable("is_public", is_public ? 1 : 0);
	loader.addVariable("tags", tags);
	loader.addVariable("title", title);
	loader.load(UPLOAD_DEST);
 
	// Indicate that the upload process started
	return true;
 
}

You can download the modified Upload.as file here.

You’ll also need download the MultipartURLLoader and MultipartURLLoaderEvent from the in-spirit google code repository.

Its very easy to use this in your application. Here is some sample code that takes a screen shot of your app and sends it to flickr:

1
2
3
4
5
6
var screenShot:BitmapData = new BitmapData(width, height);
screenShot.draw(this);
var encoder:JPEGEncoder = new JPEGEncoder(50);
var photoData:ByteArray = encoder.encode(screenShot);
upload = new Upload(flickrService);
upload.uploadBytes(photoData, "test", "test", "test", true, false, false, 0, 2, false);

Note: You must authenticate with WRITE accress using the AS3 Flickr Library authentication classes before you can upload.

7 thoughts on “Upload ByteArray to Flickr

  1. Kevin Sweeney

    Hey Danny,
    Thanks for this—it’s exactly what I needed! Did hit a snag though and I think it’s the same problem is Brian. Works fine while testing locally, but here’s the stack trace I get when trying to upload when deployed on the web:

    SecurityError: Error #2176: Certain actions, such as those that display a pop-up window, may only be invoked upon user interaction, for example by a mouse click or button press.
    at flash.net::URLStream/load()
    at flash.net::URLLoader/load()
    at ru.inspirit.net::MultipartURLLoader/doSend()
    at ru.inspirit.net::MultipartURLLoader/load()
    at com.adobe.webapis.flickr.methodgroups::Upload/uploadBytes()
    at com.kevinsweeneydesign.historyVisualizer::Main/uploadScreenshot()
    at com.kevinsweeneydesign.historyVisualizer::Main/onAuthGetToken()
    at flash.events::EventDispatcher/dispatchEventFunction()
    at flash.events::EventDispatcher/dispatchEvent()
    at MethodGroupHelper$/processAndDispatch()

    So it looks like Upload.uploadBytes needs to be called from within a MouseEvent handler (or KeyboardEvent)?

    Reply
  2. Kevin Sweeney

    Update: That was it. Just had to change the interaction flow of my application a bit. Now onto other bugs fixes and improvements! :)

    Reply
  3. qwerty

    Thank for your post but I’m looking first for an example with the AS3 Flicker Library for uploading images to Flickr, getting images from user’s computer as well. Any idea where I could find it?

    Thanks in advance!
    qwerty

    Reply
  4. Silverfern

    Thanks for putting this up. Always appreciate when someone is willing to share their expertise. I’m getting an error when I publish using the updated upload.as file you provided that ContentType and SafetyLevel are undefined. Where should these be set?
    Thanks for the help!

    Reply