POST file upload using URLRequest - actionscript-3

I have a quick question regarding POST file uploads in ActionScript 3. I am trying to upload a ByteArray from memory via POST to a server. I'm using the URLRequest class to send the data, and URLLoader because I want to monitor the progress. The relevant sections of code follows:
var uploadRequest:URLRequest = new URLRequest("http://127.0.0.1/upload.php");
uploadRequest.method = URLRequestMethod.POST;
uploadRequest.contentType = "multipart/form-data";
uploadRequest.data = myByteArray;
var uploader:URLLoader = new URLLoader;
uploader.addEventListener(ProgressEvent.PROGRESS, onUploadProgress);
uploader.addEventListener(Event.COMPLETE, onUploadComplete);
uploader.dataFormat = URLLoaderDataFormat.BINARY;
uploader.load(uploadRequest);
The problem is that I've set my callbacks to trace the upload progress, and the bytesTotal property of the ProgressEvent is always 1960 (the size of the request minus data?), even though the actual data is around 20MB and no file is uploaded even after the Complete event fires.
I've verified that upload.php functions correctly with a simple html form, and I can verify that myByteArray contains all of the data in question. Can anyone tell me what I'm doing wrong?
Edit:
I've attempted a couple of new things that I thought I should mention. The first is setting the content type to application/octet-stream instead of multipart/form-data, which had no effect other than increasing the number of bytes to 1964. I also checked the Apache error log and found the following text repeated a lot:
PHP Warning: Missing boundary in multipart/form-data POST data in Unknown on line 0
I'm guessing that Flash isn't formatting the HTTP request properly for whatever reason. Given that I created a FileReference that makes use of the same methods I set for the URLLoader to upload a file from disk, and got the expected result: the bytesTotal property matched the file size and the file was uploaded correctly.
Working from that I found a page in the Adobe developer docs that mentions uploading data to a server using FileReference.upload() by setting the data parameter of the URLRequest, so I tried the following code:
var uploadRequest:URLRequest = new URLRequest("http://127.0.0.1/upload.php");
uploadRequest.method = URLRequestMethod.POST;
uploadRequest.data = myByteArray;
fileRef = new FileReference;
fileRef.addEventListener(ProgressEvent.PROGRESS, onUploadProgress);
fileRef.addEventListener(Event.COMPLETE, onUploadComplete);
fileRef.upload(uploadRequest);
Which resulted in the following output:
ArgumentError: Error #2127: FileReference POST data cannot be type ByteArray.
I'm really stuck here. Any suggestions would be appreciated!

You should add more info to the "Content-Type" header:
uploadRequest.contentType = "multipart/form-data; boundary=<<boundary here>>";

Related

Get mime/type from MediaPromise

I am trying to make my scrips as cross-platform as possible. I am using CameraUI to fetch files and upload them to Firebase. The problem is I can only get the bytearray through the filepromise and not the file extension..or anything. According to numerous guides iOS wont let you get mediaPromise.file to get it's type. So I'm left with the question of how to get a mime/type from this bytearray I have, that I know is either an image or a video from MediaPromise.type.
MetaData or anything would help.
Following this guide gets me to a security error. Something with domains. I'm in Android and iOS so I can't do Security.allowDomain("*"); I made my own version by following this guide.
I searched and found this guide, and this works. But it only fetches the bytearray..
He wrote another article that made something that extracted data from the first 64K of the bytearray or something and displayed it in his app. He used a lib that's no longer up so I can't really go with his guide.
The code in there is the code I have in my script aside from a few UI management additions. How would I go about solving this? Is there some meta-data that always lies in the first set of bytes?
I even tried using this nice ANE, but I get an error..
You can get the mime type once the mediapromise was loaded:
cameraUI = new CameraUI();
if (CameraUI.isSupported)
{
cameraUI.addEventListener(MediaEvent.COMPLETE, onCameraUIComplete);
cameraUI.addEventListener(Event.CANCEL, onCameraUICanceled);
cameraUI.addEventListener(ErrorEvent.ERROR, onCameraError);
cameraUI.launch(MediaType.IMAGE);
}
private function onCameraUIComplete(e:MediaEvent):void
{
var mediaPromise:MediaPromise = e.data;
if (mediaPromise)
{
myLoader = new Loader();
myLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, onMediaPromiseLoaded);
myLoader.addEventListener(IOErrorEvent.IO_ERROR, onMediaPromiseLoadError);
myLoader.loadFilePromise(mediaPromise);
}
}
private function onMediaPromiseLoaded(e:Event):void
{
var myLoaderInfo:LoaderInfo = e.target as LoaderInfo;
var myByteArray:ByteArray = myLoaderInfo.bytes;
var mimeType:String = myLoaderInfo.contentType;
}
Another way is to determine the mimetype "manually" based on the file extension in mediaPromise.file.extension

FlashDevelop receives XML, Flash Pro receives JSON

I'm getting a data feed from a client's supplier.
Documention says that I can get the feed both in XML and in JSON, but that the default is XML. To get JSON I have to set a header Accept:application/json and remove Accept:application/xml header.
I have not set nor removed any headers in my code.
I'm using a normal URLLoader to load the feed.
When I navigate to the feed url in a browser, I get XML.
When I run my code in FlashDevelop, I get XML.
When I run the exact same code in Flash Pro, I get JSON.
Does anyone have any idea what is causing this in Flash Pro? Any hidden setting that can be changed?
URLRequest.method has no impact. Debug mode or not has no impact.
I'm stomped.
---------code I tried------------
var header:URLRequestHeader = new URLRequestHeader("Accept", "application/xml");
var headers:Array = [];
headers.push(header);
urlReq.requestHeaders = headers;
urlReq.method = URLRequestMethod.POST;
--------- full load code -----------
_urlLoader.addEventListener(Event.COMPLETE, validateFeedLoaded);
_urlLoader.addEventListener(IOErrorEvent.IO_ERROR, handleFeedIOerror);
_urlLoader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, handleFeedSecError);
var urlReq:URLRequest = new URLRequest(_feedUrl);
urlReq.requestHeaders = [new URLRequestHeader("Accept", "application/json")];
_urlLoader.load(urlReq);
Different clients/applications have different defaults. Different versions of the flash/air runtime may have different defaults for the accept type.
If you need consistency, then you should explicitly set the accept type in your request:
urlrequest.requestHeaders = [new URLRequestHeader("Accept", "application/json")];
This should ensure you get JSON back in both IDE's in whatever version of the runtime you're using.

Flash sandbox not enabling me getting JSON data from server - AS3

i'm setting up a local SWF file that has to display some JSON data retrieved from a remote web server in some dynamic text fields.
Code:
Security.allowDomain("api.yourserver.com");
var loader:URLLoader = new URLLoader();
var request:URLRequest = new URLRequest("http://api.yourserver.com/yourendpoint");
request.method = URLRequestMethod.GET;
request.contentType = "application/json";
loader.load(request);
loader.addEventListener(Event.COMPLETE, decodeJSON);
function decodeJSON(event:Event):void{
var loader:URLLoader = URLLoader(event.target);
var Info:Object = JSON.parse(loader.data);
cont.textfield1.text = Info.text.field1;
cont.textfield2.text = Info.text.field2;
cont.textfield3.text = Info.text.field3;
}
Control > Test - It works. When run standalone it doesn't. I get the 2028 error (sandbox violation).
What i tried:
The LoaderContext method explained here on StackOverflow but i get a 2124 error (Loaded file is an unknown type - seems like the Loader method can only be used with stuff like SWF or medias like JPG etc.);
Setting local playback as described always here on StackOverflow but it didn't help;
Setting up and exception in the Global Flash Player Trust directory as explained here but got the 2028 again;
Anyone who was able to overcome this and willing to explain how or at least pointing in the right direction?
Thanks in advance!
I think that your current published file has just assess to local files only and not network ones, that's why you got security #2028 error.
To avoid that, you can change the Local playback security for your published swf from the Publish Settings to Access network only :
If you still get security errors when testing locally ( like #2048 error ), take a look on my answer of this question to add your local swf file to the trusted locations ...
Hope that can help.

AS3 URLRequest POST Only Works When Compiled in HTML Wrapper

I'm attempting to send a POST request with data to another domain with this code:
_snapshot_id = 1369022400;
var urlRequest:URLRequest = new URLRequest("https://fuzzykittens/radar");
urlRequest.method = URLRequestMethod.POST;
urlRequest.contentType = "application/x-www-form-urlencoded";
//set variables for post
var postVars:URLVariables = new URLVariables();
postVars.snapshot = String(_snapshot_id);
urlRequest.data = postVars;
//initialize weather proccess request
weatherProcRequest = new URLLoader(urlRequest);
weatherProcRequest.addEventListener(Event.COMPLETE,
weatherProcRequest_CompleteHandler);
weatherProcRequest.addEventListener(IOErrorEvent.IO_ERROR,
weatherProcRequest_ErrorHandler);
weatherProcRequest.addEventListener(SecurityErrorEvent.SECURITY_ERROR,
weatherProcRequest_ErrorHandler);
weatherProcRequest.load(urlRequest);
When I set the flex compiler to use an HTML wrapper, the request works. When I don't use a wrapper, the request throws an io error #2032. I think it's not sending the snapshot id, but I don't know why.
Is there any obvious reason why a request would send data when debugged in an html wrapper and fail to do so when debugged outside an html wrapper?
fuzzykittens has a crossdomain.xml with
<allow-access-from domain="*" secure="false"/>
I found the issue. Adobe very briefly mentions this caveat in URLRequest's livedoc:
Note: If running in Flash Player and the referenced form has no body, Flash Player automatically uses a GET operation, even if the method is set to URLRequestMethod.POST. For this reason, it is recommended to always include a "dummy" body to ensure that the correct method is used.
When I just ran the SWF without a body, the snapshot id was not sent as a post var so the server responded differently.
It's definitely not the answer I wanted, but it feels good to know what was going on. Thank you for your comments.

Is it possible to retrieve xml from server, save to device and use that local file for my HTTPService url?

I have an app that retrieves XML From a server I run... Im trying to limit the calls to the server (if possible) to improve responsiveness of the app and decrease the likelihood that the user will get errors if the data stream doesnt make the trip successfully for whatever reason -- i get some intermittent network monitor errors, it could be due to some wifi channel conflicts I think I have, but its still is a potential weak point in the overall process and if I can work around that need to call to the server each time the user performs an 'action' within the app.
what I'd like to do is use the local storage on the device to (upon launch of the app) retrieve and save the XML data, then change my httpservice url the local file.
I have some code I used before to successfully write and read config settings to a local text file, so Im pretty sure this can be achieved, just not sure how exactly to go about it.
thanks for any light someone can shed on this or any code examples anyone can share.
Load it by default from the applicationStorageDirectory if it doesnt exist donwload and save the xml to the applicationStorageDirectory
to load:
var xmlFile:File = File.applicationStorageDirectory.resolvePath("data.xml");
if (xmlFile.exists)
{
var fileStream:FileStream = new FileStream();
fileStream.open(xmlFile, FileMode.READ);
var xml:XML = XML(fileStream.readUTFBytes(fileStream.bytesAvailable));// you will want to declare outside this scope, its just for show
fileStream.close();
}else{
downloadAndSaveXML();// if it doesnt exist dowload it then save it and call load again!
}
to save:
//download .xml first and save in the onComplete handler, im calling the file "xml"
var file:File = File.applicationStorageDirectory.nativePath("data.xml");
var stream:FileStream = new FileStream();
stream.open(file, FileMode.WRITE);
stream.writeUTFBytes(xml.toXMLString());
stream.close();
get the idea?
You will also need this compiler argument so the HTTPService doesnt look online for the xml
-locale en_US -use-network=false
You could not bother with dowloading the file in the firstplace and just embed it in the Application
here a link to the topic