In the file upload chapter of the book I show how to create a multipart request to upload an image to a Rails server. On a client project I needed to send some XML and two images in one post to a Rails application. Mike, over at
http://www.mikestead.co.uk, wrote a nice framework to create multipart requests in an ActionScript like fashion which would make this easier. You can read the whole article over at http://www.mikestead.co.uk/2009/01/04/upload-multiple-files-with-a-single-request-in-flash/. However, I tried his out and it didn't work with Rails. After some debugging and a little tweaking I made it work, you will find the fix at the end of this article. So let's look at an example (from my client project, used without authorization ;-):
private function sendToServer(planId:String, plan:XML, patternBitmap:Bitmap, layoutBitmap:Bitmap):void {
var variables:URLVariables = new URLVariables();
variables.quilt_plan = plan.toXMLString();
variables.pattern_image = new URLFileVariable(new PNGEncoder().encode(patternBitmap.bitmapData), "pattern_image.png");
variables.layout_image = new URLFileVariable(new PNGEncoder().encode(layoutBitmap.bitmapData), "layout_image.png");
var request:URLRequest = new URLRequestBuilder(variables).build();
request.url = "/quilt_plans/";
request.method = URLRequestMethod.POST;
loader = new URLLoader(request);
loader.addEventListener(Event.COMPLETE, completeHandler);
loader.load(request);
}
As you see using the URLFileVariable and URLRequestBuilder is pretty straight forward. In the above example we first add some XML to the URLVariable:
variables.quilt_plan = plan.toXMLString();
Then we add the bitmap data of an image:
variables.pattern_image = new URLFileVariable(new PNGEncoder().encode(patternBitmap.bitmapData), "pattern_image.png");
We add a second image named layout_image in the similar manner. Finally we use the build method of the URLRequestBuilder to create a multipart request.
var request:URLRequest = new URLRequestBuilder(variables).build();
This request can then be passed to the load method of a standard URLLoader to send two images and an XML document in one swoop.
On the Rails side in our controller
@quilt_plan = QuiltPlan.new(:quilt_plan_calculations => params[:quilt_plan])
@quilt_plan.build_layout_image(:uploaded_data => params[:layout_image])
@quilt_plan.build_pattern_image(:uploaded_data => params[:pattern_image])
Now the params argument passed to your Rails action method contains the XML in the params[:quilt_plan] variable, and the two images ready for upload in params[:layout_image] and params[:pattern_image]. You could do params[:layout_image].read to get the image, or as with our example the attachment_fu plugin does it for us.
Et voila...happy multipart requesting!
Rails did have issues with the way the request was created and I applied the following changes which mainly just changes the Line Feed send in the requests in URLRequestBuilder.as:
< private static const LF:String = "\r\n";
---
> private static const LF:String = "\n";
187,188c185
< field.writeUTFBytes(MULTIPART_MARK + MULTIPART_BOUNDARY + LF +
---
> field.writeUTFBytes(LF + MULTIPART_MARK + MULTIPART_BOUNDARY + LF +
191a189
>
208,209c206
< field.writeUTFBytes(MULTIPART_MARK + MULTIPART_BOUNDARY + LF +
---
> field.writeUTFBytes(LF + MULTIPART_MARK + MULTIPART_BOUNDARY + LF +
Enjoy!
Daniel