upload a zip file using HTTP POST via actionscript 3.0 - actionscript-3

I have a zip file that is created using drag and drop on a view in my desktop Flex 4.6 app.
This triggers a service that will automatically upload the zip file.
I am able to use the following code to send metadata about the zip file to the server.
var urlRequest:URLRequest = new URLRequest(PUBLISH_ZIP_FILE_URL);
// set to method=POST
urlRequest.method = URLRequestMethod.POST;
var params:URLVariables = new URLVariables();
params['data[File][title]'] = 'Title1';
params['data[File][description]'] = 'desc';
// params['data[File][filename]'] = I am not sure exactly what to use here
// If this is a webpage, I expect to use input type="file" with the name as data[File][filename]
urlRequest.data = params;
addLoaderListeners();
// set it such that data format is in variables
loader.dataFormat = URLLoaderDataFormat.VARIABLES;
loader.load(urlRequest);
I have read https://stackoverflow.com/questions/8837619/using-http-post-to-upload-a-file-to-a-website
However, immediately they start off with ByteArray, which I am not sure how to convert my zip file at all.
Please advise.

Embarrassing but I found my answer 42 mins after I posted the question.
A little bit of a rubber duck problem solving going on here.
http://www.codinghorror.com/blog/2012/03/rubber-duck-problem-solving.html
Short answer: Use File class and specifically the method upload which is extended from the FileReference class.
Long answer:
var urlRequest:URLRequest = new URLRequest(PUBLISH_ZIP_FILE_URL);
// set to method=POST
urlRequest.method = URLRequestMethod.POST;
var params:URLVariables = new URLVariables();
params['data[File][title]'] = 'Title1';
params['data[File][description]'] = 'desc';
// this is where we include those non file params and data
urlRequest.data = params;
// now we upload the file
// this is how we set the form field expected for the file upload
file.upload(urlRequest, "data[File][filename]");

Related

Sending data to a JSON with AS3

I've asked my client to share his database login and password but he can't give me full access to his database (security reason I suppose).
He told me to use a REST/JSON service that allows to post the data via this url with a specific key that allows him to identify all the datas coming from my app.
Here's what I did :
var urlRequest:URLRequest = new URLRequest("the_url_using JSON service");
urlRequest.method = URLRequestMethod.POST;
var urlvars: URLVariables = new URLVariables;
urlvars.observer_name = "Test Coco";
urlvars.observation_number = "5433";
trace("urlvars = "+urlvars);
urlRequest.data = urlvars;
var urlLoader:URLLoader = new URLLoader();
urlLoader.addEventListener(Event.COMPLETE, onComplete);
urlLoader.load(urlRequest);
It's working, as it's sending the data, but the data format seems to be incorrect..
the url returns this error : "Observer name is Missing"
And the "trace (urlvars)" output :
urlvars = observer%5Fname=Test%20Coco&observation%5Fnumber=5433
So I think the problem come from the special character or something like that (as you can "observer_name" results by "observer%5Fname" and we can see a lot of %5")
Any idea how can I solve this ?
JSON string is a string representation of a generic object. Basically you go:
var anObject:Object =
{
"observer_name": "Test Coco",
"observation_number": 5433
};
or you can construct it
var anObject:Object = new Object;
anObject['observer_name'] = "Test Coco";
anObject['observation_number'] = 5433;
and then you convert it to String and attach to request
var jsonString:String = JSON.stringify(anObject);
urlRequest.method = URLRequestMethod.POST;
urlRequest.data = jsonString;
Read more about it: https://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/JSON.html
Keep in mind that I don't know the specifics of that REST server of yours and the code above just might not work as it is. I only explain how to send a JSON string as a POST request.

FileReference.save ensuring it has extension

I need to save an XML with some settings and wanted to save them as my own filetype (.genconf for example). When i use..
var f:FileReference = new FileReference();
f.save( MyByteArray);
..I can allow the user to browse to save, but it only uses an extension if they enter in manually (which they definitely wont).
Is there a way to check the filename they enter, and amend/append it before the file is written?
Here's how i did it in the end (with AIR):
//on save clicked
public function export(e:MouseEvent){
var file:File = File.desktopDirectory;
file.browseForSave("Save");
file.addEventListener(Event.SELECT, onSaveSelect);
}
public function onSaveSelect(e:Event){
//create XML stuff here
var config:XML = new XML(<config />)
// compressing before saving
var bytes:ByteArray = new ByteArray();
bytes.writeUTFBytes( config );
bytes.compress();
//get browse location
var saveFile:File = File(e.target);
var directory:String = saveFile.url;
//check if by miracle they put the extension in, then add it
if(directory.indexOf(".genconf ") == -1){
directory += ".genconf ";
}
//use the new path with the extension
var file:File = new File();
file = file.resolvePath(directory);
var fileStream:FileStream = new FileStream();
fileStream.addEventListener(Event.CLOSE, onClose);
fileStream.openAsync(file, FileMode.WRITE);
fileStream.writeBytes(bytes);
fileStream.close();
}
I think that for Flash security reason you can not force the file extension in any way, in addition the file name typed by user is a read-only information so you can not modify it.
So for your case, you want to save files with the .genconf extension, I think that you can :
Request the file name to your user, before showing the save dialog, and then add the extension to have the default file name for the save dialog.
OR
Fix the default file name with your extension using time-stamp, randomized name, ... and demand to your user to save the file directly without editing the name.
In all cases, you will get a code like this :
const extension:String = '.genconf';
var file_ref:FileReference = new FileReference()
file_ref.save('your_data', 'default_file_name' + extension);
Hope that can help.

specifying the "request method" in externalinterface.call method?

When the user try to download the file ,i need to open a new html window and download the file , currently iam using "ExternalInterface.call" but i need to set the "requestmethod" otherwise server is throwing the error ,how to specify "requestmethod"?
Why not use the global navigateToURL method? You can pass in a URLRequest object which has a property called method and will solve your problem.
So you need something like this:
var request:URLRequest = new URLRequest("http://example.com");
request.method = URLRequestMethod.POST; // or anything you want
// parameters can be added to a URLVariables object
// which then can be set as requests data property
// example:
var params:URLVariables = new URLVariables();
params.username = "test";
params.password = "123";
request.data = params;
// load the page
// specify '_blank' parameter to open it in a new browser window
navigateToURL(request, "_blank");

Upload file to server without using FileReference.browse()

I am trying to upload file to server with the FileReference class.
the file is mp3 that was encoded in runtime without saving him on the local hard drive.
Is it possible to fit in the mp3Encoder into the FileReference somehow?
Thanks
Assuming you have the mp3 as a ByteArray (not sure how else it would exist at runtime if you haven't saved it to disk), you can use the URLLoader class, like this:
var scriptRequest:URLRequest = new URLRequest("PATH_TO_YOUR_UPLOAD_SCRIPT");
var scriptLoader:URLLoader = new URLLoader();
var scriptVars:URLVariables = new URLVariables();
scriptLoader.addEventListener(Event.COMPLETE, handleLoadSuccessful);
scriptLoader.addEventListener(IOErrorEvent.IO_ERROR, handleLoadError);
scriptVars.var1 = MP3_AS_BYTE_ARRAY;
scriptRequest.method = URLRequestMethod.POST;
scriptRequest.data = scriptVars;
scriptLoader.load(scriptRequest);
function handleLoadSuccessful($evt:Event):void
{
trace("Message sent.");
}
function handleLoadError($evt:IOErrorEvent):void
{
trace("Message failed.");
}
Then on the server, you just need to save the stream to a file and give it the correct mp3 mime type.
There's a decent tutorial, from which this example is adapted, here: http://evolve.reintroducing.com/2008/01/27/as2-to-as3/as2-%E2%86%92-as3-loadvars-as3-equivalent/
And if you need to send your request as multipart/form-data (so it appears to be an attached file), there's a good example of this here: http://marstonstudio.com/2007/10/19/how-to-take-a-snapshot-of-a-flash-movie-and-automatically-upload-the-jpg-to-a-server-in-three-easy-steps/

Sending POST variables via an AIR application

I'm trying to send data via POST, since it's far too long to send via GET.
Here's the code I'm using...
pdfUrl.method = URLRequestMethod.POST;
var vars:URLVariables = new URLVariables();
vars.html = data;
pdfUrl.data = vars;
navigateToURL(pdfUrl);
The problem is that it always sends as GET, and the data in vars.html is too long for my server to receive.
To make matters worse, it seems like AIR can only send GET via navigateToURL.
The issue with this is, I need to open a new browser window and send the POST data so that a script on my server can create a PDF file for the user.
What workarounds are there for this?
I'm not aware of any way to open a new browser window with a POST request, with GET being the default HTTP method used to open pages (which makes sense, really). An alternative, however, would be to POST the data using a simple HTTP request in AIR and once you get a response to the POST request in AIR, you can open a new browser window using a GET request.
So:
POST to your server directly from AIR.
Have your server return some kind of value that you can use in step 3.
Open a new browser window using navigateToURL and attach the value you got from step 2 to the URL.
This should work well, I think.
// Upload MP3-Byte-Array
private function uploadFile():void
{
var uploadURL:URLRequest = new URLRequest();
uploadURL.url = "myfile.php?var1=var1Value&var2=var2Value";
uploadURL.contentType = 'application/octet-stream';
uploadURL.method = URLRequestMethod.POST;
uploadURL.data = heavyDataThatyouWantToPass;
var urlLoader:URLLoader = new URLLoader();
urlLoader.addEventListener(Event.COMPLETE, completeHandler);
urlLoader.load(uploadURL);
}
private function completeHandler(event:Event):void
{
var loader:URLLoader = URLLoader(event.target);
}
myfile.php will be like this:
<?php
$var1 = $_REQUEST['var1Value'] ;
$var2 = $_REQUEST['var2Value'] ;
$heavyData = $GLOBALS[ 'HTTP_RAW_POST_DATA' ];?>