У меня есть гибкое приложение, которое хочет загрузить два изображения на сервер rails в одном запросе POST. Я думаю, что я создаю часть данных запроса POST, но я не уверен. Когда я печатаю параметры, поступившие со стороны рельсов, я вижу только один файл.
public class MultipartDataHandler extends EventDispatcher
{
//<net:URLLoader id="loader" complete="completeHandler(event)" dataFormat="binary" />
private var loaderContext:LoaderContext = new LoaderContext(true);
private var loader:URLLoader = new URLLoader();
public function MultipartDataHandler()
{
}
public function sendToServer(exteriorBitmapData:BitmapData, interiorBitmapData:BitmapData):void {
var xml_file:String = UserPreference.getInstance().toXML().toXMLString();
var gongos_id:int = UserPreference.getInstance().gongosId;
var room_id:int = UserPreference.getInstance().roomId;
var car_id:int = UserPreference.getInstance().theCar.id;
// 1. Encode image as a png
// var bitmap:Bitmap = image.content as Bitmap;
// var bytes:ByteArray = pngEncoder.encode(bitmap.bitmapData);
var pngEncoder:PNGEncoder = new PNGEncoder();
var exteriorBytes:ByteArray = pngEncoder.encode(exteriorBitmapData);
var interiorBytes:ByteArray = pngEncoder.encode(interiorBitmapData);
// 2. Create multip part request
var boundary:String = '------------Ij5GI3GI3ei4GI3ei4KM7GI3KM7KM7';
var url:String = UserPreference.urlize("/cars/upload.xml");
var request: URLRequest = new URLRequest(url);
request.data = getMultiPartRequestData(boundary, 'car', exteriorBytes, interiorBytes, xml_file, gongos_id, room_id, car_id);
request.method = URLRequestMethod.POST;
request.contentType = "multipart/form-data; boundary=" + boundary;
// 3. Send to Server
loader.load(request);
loader.addEventListener(IOErrorEvent.IO_ERROR, errorHandler);
loader.addEventListener(Event.COMPLETE, loaderCompleteHandler);
}
private function getMultiPartRequestData(boundary:String, resourceName:String,
exteriorBytes:ByteArray,
interiorBytes:ByteArray,
xml_file:String,
gongos_id:int, room_id:int, car_id:int):ByteArray {
var lf:String = "\r\n";
var part1:String = '--' + boundary + lf +
'Content-Disposition: form-data; name="Filename"' + lf + lf +
'{0}' + lf +
'--' + boundary + lf +
'Content-Disposition: form-data; name="{1}[xml]"' + lf + lf +
'{2}' + lf +
'--' + boundary + lf +
'Content-Disposition: form-data; name="gongos_id"' + lf + lf +
'{3}' + lf +
'--' + boundary + lf +
'Content-Disposition: form-data; name="room_id"' + lf + lf +
'{4}' + lf +
'--' + boundary + lf +
'Content-Disposition: form-data; name="car_id"' + lf + lf +
'{5}' + lf +
'--' + boundary + lf +
'Content-Disposition: form-data; name="{1}[photo]"; ' +
'filename="{0}"' + lf +
'Content-Type: application/octet-stream' + lf +lf;
var part2:String = '--' + boundary + lf +
'Content-Disposition: form-data; name="{1}[interior_photo]"; ' +
'filename="{0}"' + lf +
'Content-Type: application/octet-stream' + lf +lf;
var part3:String = '--' + boundary + lf +
'Content-Disposition: form-data; name="Upload"' + lf + lf +
'Submit Query' + lf +
'--' + boundary + '--';
part1 = StringUtil.substitute(part1, 'car.png', resourceName,
xml_file, gongos_id, room_id, car_id);
part2 = StringUtil.substitute(part2, 'interior.png', resourceName);
var result:ByteArray = new ByteArray();
result.writeMultiByte(part1, "ascii");
result.writeBytes(exteriorBytes, 0, exteriorBytes.length)
result.writeMultiByte(part2, "ascii");
result.writeBytes(interiorBytes, 0, interiorBytes.length)
result.writeMultiByte(part3, "ascii");
trace(part1 + "EXTERIOR BYTES" + part2 + "INTERIOR BYTES" + part3);
return result;
}
}
}
Это то, что печатает консоль отладки. Обратите внимание, что я не печатаю фактические байты в консоли, так как это было бы очень больно, но вы можете видеть, куда они идут.
--------------Ij5GI3GI3ei4GI3ei4KM7GI3KM7KM7
Content-Disposition: form-data; name="Filename"
car.png
--------------Ij5GI3GI3ei4GI3ei4KM7GI3KM7KM7
Content-Disposition: form-data; name="car[xml]"
<creation>
<car>
<bodyId>1</bodyId>
<themeId>0</themeId>
<roomId>0</roomId>
<userId>0</userId>
<name>null</name>
<exterior/>
<interior/>
</car>
</creation>
--------------Ij5GI3GI3ei4GI3ei4KM7GI3KM7KM7
Content-Disposition: form-data; name="gongos_id"
0
--------------Ij5GI3GI3ei4GI3ei4KM7GI3KM7KM7
Content-Disposition: form-data; name="room_id"
1
--------------Ij5GI3GI3ei4GI3ei4KM7GI3KM7KM7
Content-Disposition: form-data; name="car_id"
0
--------------Ij5GI3GI3ei4GI3ei4KM7GI3KM7KM7
Content-Disposition: form-data; name="car[photo]"; filename="car.png"
Content-Type: application/octet-stream
EXTERIOR BYTES--------------Ij5GI3GI3ei4GI3ei4KM7GI3KM7KM7
Content-Disposition: form-data; name="car[interior_photo]"; filename="interior.png"
Content-Type: application/octet-stream
INTERIOR BYTES--------------Ij5GI3GI3ei4GI3ei4KM7GI3KM7KM7
Content-Disposition: form-data; name="Upload"
Submit Query
--------------Ij5GI3GI3ei4GI3ei4KM7GI3KM7KM7--
И, наконец, вот что говорит Rails.
--- !map:HashWithIndifferentAccess
room_id: "1"
Filename: car.png
format: xml
action: upload
car_id: "0"
controller: cars
car: !map:HashWithIndifferentAccess
photo: !ruby/object:File {}
xml: |-
<creation>
<car>
<bodyId>1</bodyId>
<themeId>0</themeId>
<roomId>0</roomId>
<userId>0</userId>
<name>null</name>
<exterior/>
<interior/>
</car>
</creation>
gongos_id: "0"
Processing CarsController#upload to xml (for 127.0.0.1 at 2011-03-17 08:05:00) [POST]
Parameters: {"Filename"=>"car.png", "room_id"=>"1", "car_id"=>"0", "car"=>{"photo"=>#<File:/var/folders/f6/f6zP-E52HiaycvHwz90OtE+++TI/-Tmp-/RackMultipart20110317-24400-14hcvab-0>, "xml"=>"<creation>\n <car>\n <bodyId>1</bodyId>\n <themeId>0</themeId>\n <roomId>0</roomId>\n <userId>0</userId>\n <name>null</name>\n <exterior/>\n <interior/>\n </car>\n</creation>"}, "gongos_id"=>"0"}
[paperclip] identify '-format' '%wx%h' '/var/folders/f6/f6zP-E52HiaycvHwz90OtE+++TI/-Tmp-/stream,24400,0.png[0]' 2>/dev/null
[paperclip] convert '/var/folders/f6/f6zP-E52HiaycvHwz90OtE+++TI/-Tmp-/stream,24400,0.png[0]' '-resize' '500x500>' '/var/folders/f6/f6zP-E52HiaycvHwz90OtE+++TI/-Tmp-/stream,24400,0,24400,0' 2>/dev/null
[paperclip] identify '-format' '%wx%h' '/var/folders/f6/f6zP-E52HiaycvHwz90OtE+++TI/-Tmp-/stream,24400,0.png[0]' 2>/dev/null
[paperclip] convert '/var/folders/f6/f6zP-E52HiaycvHwz90OtE+++TI/-Tmp-/stream,24400,0.png[0]' '-resize' '250x250>' '/var/folders/f6/f6zP-E52HiaycvHwz90OtE+++TI/-Tmp-/stream,24400,0,24400,1' 2>/dev/null
User Load (0.3ms) SELECT * FROM "users" WHERE ("users"."gongos_id" = '0' AND "users"."room_id" = '1') LIMIT 1
Car Create (81.1ms) INSERT INTO "cars" ("name", "interior_photo_file_name", "room_id", "photo_file_size", "interior_photo_file_size", "interior_photo_updated_at", "created_at", "xml", "photo_file_name", "updated_at", "body_id", "photo_content_type", "deleted", "user_id", "interior_view_id", "theme_id", "photo_updated_at", "parent_car_id", "interior_photo_content_type") VALUES('Faxo', NULL, NULL, 102547, NULL, NULL, '2011-03-17 12:05:03', '<creation>
<car>
<bodyId>1</bodyId>
<themeId>0</themeId>
<roomId>0</roomId>
<userId>0</userId>
<name>null</name>
<exterior/>
<interior/>
</car>
</creation>', 'car.png', '2011-03-17 12:05:03', 1, 'application/octet-stream', NULL, NULL, NULL, 0, '2011-03-17 12:05:01', NULL, NULL)
[paperclip] Saving attachments.
[paperclip] saving /Users/glurban/code/amfdreamcar/public/system/photos/18/medium/car.png
[paperclip] saving /Users/glurban/code/amfdreamcar/public/system/photos/18/original/car.png
[paperclip] saving /Users/glurban/code/amfdreamcar/public/system/photos/18/thumb/car.png
[paperclip] Saving attachments.
Rendering cars/upload
Completed in 2750ms (View: 60, DB: 81) | 200 OK [http://localhost/cars/upload.xml]
Итак, как видите, в параметрах появляется только одна фотография (первая). При переключении заказа появляется только interior_photo
. Что я делаю не так?
Я также пытался сделать два отдельных вызова, соединенных вместе, но это не удалось из-за ограничения безопасности Flash 10, которое запрещает загрузку файлов без выполнения пользователем какого-либо действия, например нажатия кнопки. Я даже попытался поместить оба вызова на loader.load()
в одной и той же функции, используя генератор случайных чисел для создания идентификатора на гибкой стороне (потому что рельсы должны знать, что эти два вызова относятся к одной и той же машине, и без объединения Я не могу использовать ответ от первого вызова для передачи идентификатора машины), но я столкнулся с состоянием гонки, когда второй вызов каким-то образом попал на сервер до первого. Безопасность Adobe ... FFFFFFFUUUUUU.