I am converting a Flash application to AIR. One feature we use is navigateToURL to run reports. The tool we use accepts POST variables and creates a stream of data which renders a PDF report. In reading through everything I can find the navigateToURL does not support POST, it converts it to GET. This causes a problem.
I have implemented a “File” object, using the “download” method, and it retrieves the data stream and allows the user to choose where to save it and then I have code that automatically opens the file with the default application. What I would prefer is to accept the data stream and send it directly to the default browser with the appropriate mime type, so that the browser can open it.
I have been unable to find anything which indicates this is possible in AS3/AIR. If it is possible I would appreciate a pointer to the documentation, and/or examples on how it can be done.
If you look at navigateToURL() documentation, it does support POST but under condition
In Flash Player 10 and later, if you use a multipart Content-Type (for example “multipart/form-data”) that contains an upload (indicated by a “filename” parameter in a “content-disposition” header within the POST body), the POST operation is subject to the security rules applied to uploads:
The POST operation must be performed in response to a user-initiated action, such as a mouse click or key press.
If the POST operation is cross-domain (the POST target is not on the same server as the SWF file that is sending the POST request), the target server must provide a URL policy file that permits cross-domain access.
Also, for any multipart Content-Type, the syntax must be valid (according to the RFC2046 standards). If the syntax appears to be invalid, the POST operation is subject to the security rules applied to uploads.
That said, both methods navigateToURL() and sendToURL() are underneath using an HTTP client to send those requests.
So even if I don’t fully follow what your tool is doing, I would ay the best bet is to implement your own HTTP client based on Socket and docs related to HTTP and POST.
OK so I got few questions.
The AIR app connect to an HTTP server, and send POST request
does the request is user-initiated ? eg. someone clicking a button
or do you want it to behave more like an automated process ?
what kind of data are you sending ?
just variables? JSON? bytes?
and finally do you need to receive back data?
you can send a POST request as “fire and forget” without caring about the returned response
or you may need to “validate” or “proof of receipt” by getting a response
That’s where I get lost, in which direction the data transfer occurs?
Is it your AIR client requesting a server and you want to receive a stream of data?
Or the AIR client waiting some actions/events to send back a stream of data?
Assuming the case is the following
user click in your AIR client
the AIR client send a POST request to a server
then the AIR client receive the response from that server
All this should work with the API you have in AIR.
Now, building a small HTTP client is not that hard and can allow you more control on how the data is sent.
In short, the HTTP protocol is text-based, and in general if you follow HTTP/1.1 there are just few rules to follow.
application/x-www-form-urlencoded : the keys and values are encoded in key-value tuples separated by '&' , with a '=' between the key and the value. Non-alphanumeric characters in both keys and values are percent encoded: this is the reason why this type is not suitable to use with binary data (use multipart/form-data instead)
multipart/form-data : each value is sent as a block of data (“body part”), with a user agent-defined delimiter (“boundary”) separating each part. The keys are given in the Content-Disposition header of each part.
let’s see few examples
A basic POST request using application/x-www-form-urlencoded
look like that
POST /test HTTP/1.1
that same request when it is transformed to a GET request gives something like that
GET /test?field1=value1&field2=value2 HTTP/1.1
The differences are
the data, the variables value-pair
with a GET request is send the URL path
with a POST request is send into the body of the request
a GET request is limited in the amount of data
so you should use it only for “small” amount of data
(usually 2048 characters)
with a GET request the data will show in server logs
for some use case it is not secure to do that
But as long as you want only to send value-pairs and small amount of data, GET or POST will get you the same result.
Now if you want to send a POST request with multipart/form-data, there things get real different
A POST request using text/plain would look like that
POST /test HTTP/1.1
hello the big world
But all those are in the context of browsers “classic usage”, in the MDN doc the thing to notice is that
When the POST request is sent via a method other than an HTML form — like via an XMLHttpRequest — the body can take any type. As described in the HTTP 1.1 specification, POST is designed to allow a uniform method to cover the following functions:
Annotation of existing resources
Posting a message to a bulletin board, newsgroup, mailing list, or similar group of articles;
Adding a new user through a signup modal;
Providing a block of data, such as the result of submitting a form, to a data-handling process;
Extending a database through an append operation.
eg. “the body can take any type”
and that’s how you send JSON data from a browser to a server for ex:
public function getFileFromURL(urlToGet:URLRequest, strDefaultFileName:String):void
_objDownloadFile = new File;
private function fileCompletionHandler(event:Event):void
var strFilePath:String = _objDownloadFile.nativePath;
var file:File = File.applicationDirectory.resolvePath(strFilePath);
Typically the data being sent is name value pairs, (name1=value1)
The report generator sends back a properly mime typed data and does not require an “ACK”.
The Flash application using the code above, gets information from the user/app, sends a request off to the report generator using POST, it then pops up a new browser window/tab (_blank) with the pdf report in it. I would like to emulate this, however when I try to use navigateToURL in Adobe AIR, all of the name/variable pairs appear on the url (http://xyz.com/report.aspx?argument1=value1&Argument2=value2…).
If there is a way in AIR to send POST variables, and have it pop up a default browser with the results I would be happy with that.
If not, my thought was to use some other oject which implements the URLRequest, capture the stream of data, and then send the stream of data to the default browser. It will already have the appropriate HTML/mime stuff in the data stream. I do not know what objects & methods are needed to implement this.
Since No one had an answer, what I implemented was to create a temporary folder when you first “print” (create a pdf) something. I automatically download the pdf to the temporary folder and fire up the default pdf viewer.
When I close the app I delete the temporary folder and contents. When I start the app, I look to see if the folder exists and delete it before I start. It isn’t perfect, but it gets the job done.