ActionScritp3 multipart/form-dataでデータのアップロード
7月 31st, 2013モバイルAIRでカメラ撮影した写真をmultipart/form-dataでWebにアップする流れのメモ。
写真がbitmapDataという段階からスタート。
// Jpeg 変換
var byteArray:ByteArray = new ByteArray();
bitmapData.encode(bitmapData.rect, new flash.display.JPEGEncoderOptions(), byteArray);
// Base64 変換
var base64Encoder:Base64Encoder = new mx.utils.Base64Encoder();
base64Encoder.encodeBytes(byteArray);
// POSTデータ作成
var formBuilder:MultipartFormDataBuilder = new jp.psyark.net.MultipartFormDataBuilder("207542376適当");
formBuilder.addPart("apiKey", "123456ホゲ");
formBuilder.addPart("inputFile", byteArray, "dummyName.jpg", true);
var urlRequest:URLRequest = new URLRequest(url);
formBuilder.configure(urlRequest);
var urlLoader:URLLoader = new URLLoader();
// ここらでイベントリスナーの追加処理。
urlLoader.load(urlRequest);
問題はPOSTデータの作成のところ。
http://www.libspark.org/wiki/psyark/MultipartFormDataBuilder
にあるMultipartFormDataBuilderを利用しましたが、うまくいきませんでした。
そんなとき、[AS3] PHPとAS3の連携 multipart/form-dataでデータのアップロード http://www.kuma-de.com/blog/2010-10-07/2352 が大変参考になりました。
ただ、このサイトのMultipartFormDataBuilder.asでもまだ動きませんでした。結論としては、追記にある最後のバウンダリの問題が原因でした。そこで、addPartの第4引数 last を追加して、バウンダリの最後に「–」が追加されるように修正しました。受け取り側をphpで実装した場合は、必要なかったです。javaのtomcatだと最後の「–」が必要でした。
理想的な修正は、configure()実行時に「–」を追加することかな。最後かどうかはコード側で勝手に判断してくれれば十分ですね。あと、Content-Type:もベタ書きも直さないと思いつつそのままw
package jp.psyark.net {
import flash.net.URLRequest;
import flash.net.URLRequestMethod;
import flash.utils.ByteArray;
/**
* multipart/form-dataのリクエストを作成するための簡単なクラスです。
*/
public class MultipartFormDataBuilder {
protected var _boundary:String;
protected var byteArray:ByteArray;
/**
* コンストラクタです。
*
* @param boundary バウンダリ(境界線)文字列です。送信する他のデータ中に出現しない文字列である必要があります。
*/
public function MultipartFormDataBuilder(boundary:String) {
_boundary = boundary;
byteArray = new ByteArray();
addBoundary();
}
/**
* パート(部分)を追加します。
*
* @param name このパートの名前です。content-dispositionヘッダのname属性に使われます。
* @param data このパートのデータです。ByteArray以外の値は文字列として評価されます。
* @param filename このパートのファイル名です。null以外の値を渡した場合、content-dispositionヘッダのfilename属性に使われます。
* @param last 最後のパートの時だけtrueにする。バウンダリに最後を意味する--を追加する。
*/
public function addPart(name:String, data:*, filename:String=null, last:Boolean = false):void {
byteArray.writeUTFBytes('Content-disposition: form-data; name="' + name + '"');
if (filename != null) {
byteArray.writeUTFBytes('; filename="' + filename + '"');
byteArray.writeUTFBytes("\r\n");
byteArray.writeUTFBytes("Content-Type: image/jpeg"); //JPEG用
}
byteArray.writeUTFBytes("\r\n\r\n");
if (data is ByteArray) {
byteArray.writeBytes(data);
} else {
byteArray.writeUTFBytes(data);
}
byteArray.writeUTFBytes("\r\n");
addBoundary(last);
}
/**
* multipart/form-dataのリクエストとして使えるように、URLRequestを設定します。
*/
public function configure(request:URLRequest):void {
request.method = URLRequestMethod.POST;
request.data = byteArray;
request.contentType = "multipart/form-data; boundary=" + _boundary;
}
private function addBoundary(last:Boolean = false):void {
if (last) {
byteArray.writeUTFBytes("--" + _boundary + "--\r\n");
} else {
byteArray.writeUTFBytes("--" + _boundary + "\r\n");
}
}
}
}