How do I send a bytearray to server and detect progress? - actionscript-3

I am using Flash runtime (flash player 10). I have a flv encoded bytearray which I need to send to the server( simple php, no FMS or socket servers) and save there. I can use the urlLoader and post everything but then i won't get the progress percentage, so instead I tried saving it with a file reference like this:
var url_ref:URLRequest = new URLRequest("save_vid.php");
url_ref.contentType = "multipart/form-data; boundary="+getBoundary();
url_ref.data = _baFlvEncoder.byteArray;
url_ref.method = URLRequestMethod.POST;
var upfileRef:FileReference = new FileReference();
upfileRef.addEventListener(ProgressEvent.PROGRESS, onUploadProgress);
upfileRef.addEventListener(Event.COMPLETE, videoUploadComplete);
upfileRef.upload(url_ref);
But when I try this, I am getting an error:
Error #2037: Functions called in incorrect sequence, or earlier call was unsuccessful.
Any idea how I can do this?

Try this:
var vars :URLVariables = new URLVariables();
vars.bytearray = _baFlvEncoder.byteArray;
var req :URLRequest = new URLRequest("save_vid.php");
req.method = URLRequestMethod.POST;
req.data = vars;
var ldr :URLLoader = new URLLoader();
ldr.addEventListener( Event.COMPLETE, onLoaded );
ldr.addEventListener( IOErrorEvent.IO_ERROR, onIOError );
ldr.addEventListener( ProgressEvent.PROGRESS, onProgress );
ldr.load( req );
function onProgress( e:ProgressEvent ):void
{
trace( "Progress: " + e.bytesLoaded / e.bytesTotal );
}
and in PHP
$bytearray = $_POST['bytearray']

Related

getting POST using URLRequest + if statement syntax issue

I'm trying to get the reply from the address specified in var url:String, which is either 0 or 1. If the reply is 1 then it must set currentState = CallFailed (as seen below). The client compiles without error (using Adobe Flash Builder 4.6) and seems to successfully reach var url:String, but doesn't seem to be getting the response\and or my if statement is incorrect.
Actionscript:
// check to see if block.php replies 0 or 1
var url:String = "https://domain.com/block.php?postid=" + calleeInput.text + "";
var request:URLRequest = new URLRequest(url);
var variables:URLVariables = new URLVariables();
request.data = variables;
request.method = URLRequestMethod.POST;
navigateToURL(request);
if (request.data == 1)
{
// if reply is 1 then cancel the call
currentState = CallFailed;
return;
}
PHP:
PHP will echo 0 or 1 when block.php is loaded. It's not encoded in any format such as JSON\AJAX.
It seems you want data from the server. Perhaps the URLLoader class would be better?
var url:String = "https://domain.com/block.php?postid=" + calleeInput.text + "";
var request:URLRequest = new URLRequest(url);
var variables:URLVariables = new URLVariables();
request.data = variables;
request.method = URLRequestMethod.POST;
var loader:URLLoader = new URLLoader();
loader.dataFormat = URLLoaderDataFormat.TEXT;
loader.addEventListener( Event.COMPLETE,
function( e:Event ) : void
{
// your response data will be here
// you'll have to verify the format
trace( e.target.data );
}
)
loader.load( request );
Put a breakpoint at the trace statement and check out the contents of e.target.data, and go from there
The purpose of navigateToURL() is to open the webbrowser, as stated in its documentation:
Opens or replaces a window in the application that contains the Flash Player container (usually a browser). In Adobe AIR, the function opens a URL in the default system web browser
In order to perform an request (without opening a browser, just the HTTP communication) you should use URLLoader.
The URLLoader class downloads data from a URL as text, binary data, or URL-encoded variables.
On a related note: your logic is not valid. The call to a server is asynchronous. You have to wait for the response to be returned before reasoning about the result.
The URLLoader class dispatches a number of Events that help you decide when the result of a request is returned or if there's a problem with it.

Get response status code from flash Sound object

I have music player which downloads and plays music (it should play while downloading), currently my code looks like this:
sound = new Sound(new URLRequest(url_stream));
Sometimes server returns 404 (Not Found) and 429 (Too many requests) status codes instead of music file, I'm looking for way to find out response status code in case of playback error, any ideas?
To get the response status, you can use HTTPStatusEvent event with an URLLoader like this :
var sound:Sound
var request:URLRequest = new URLRequest('http://www.example.com/file.mp3')
var loader:URLLoader = new URLLoader()
loader.addEventListener(
HTTPStatusEvent.HTTP_STATUS,
function(event):void {
trace('http status: ' + event.status)
if(event.status == 200){
sound = new Sound(request)
sound.play()
}
}
)
loader.addEventListener(IOErrorEvent.IO_ERROR, function(){})
loader.load(request)
This code is working 100%.
In akmozo's solution, you're downloading the MP3 twice. First to see if the file exists on the server, then once more to play it in the Sound. It would be better to do it like this:
var sound:Sound;
var request:URLRequest = new URLRequest('http://www.example.com/file.mp3');
var loader:URLLoader = new URLLoader();
var httpCode:int;
loader.dataFormat = URLLoaderDataFormat.BINARY;
loader.addEventListener(HTTPStatusEvent.HTTP_STATUS,loaderStatus);
loader.addEventListener(Event.COMPLETE,loaderComplete);
function loaderStatus(evt:HTTPStatusEvent):void {
httpCode = evt.status;
}
function loaderComplete(evt:Event):void {
if (httpCode == 200) {
ba:ByteArray = loader.data as ByteArray;
sound = new Sound();
sound.loadCompressedDataFromByteArray(ba,ba.length);
sound.play();
}
}
Although if the URLRequest is cached, maybe it doesn't get downloaded twice.

AIR AS3 for Mobile - Download zip file crash the application

I've make an application with AIR and ActionScript 3 ( Using the IntelliJ IDE )
At start of the application, it loads some zip file and extracts their files to put them in the local storage. For futur use ( Or an utilisation if the user kills then re-opens the application )
It works correctly without problem the most of the time except that I have, sometimes, with a very low rate of appearence, a crash of the application during the download of those zip files.
The strange thing is these crash can occur directly in the emulator on my computer ( With a message that indicates an error in AIR ).
It is really difficult to check because these crashes may occur, something, like one time on forty launches and seems to never occur when trace() are with the debug mode.
That makes me think it's probably a problem with the speed of the loading, because all trace() slows down the launches and files loading.
Apparently, it's not a memory crash. I've tested and used the same code to load a really high number of same zip together and it doesn't crash.
I can't directly show the code, because it is implanted in a more complex framework.
The concerned code is something near to this :
private static function fileLoad( url:String ):void
{
var loader:URLLoader = new URLLoader();
var header:URLRequestHeader = new URLRequestHeader( "pragma" , "no-cache" );
loader.dataFormat = URLLoaderDataFormat.BINARY;
loader.addEventListener( Event.COMPLETE, complete );
var request:URLRequest = new URLRequest( url );
request.requestHeaders.push( header );
request.method = URLRequestMethod.GET;
loader.load( request );
}
private static function complete( event:Event ):void
{
var file:File;
file = File.applicationStorageDirectory.resolvePath( "ZIP.zip" );
var bytes:ByteArray = event.target.data as ByteArray;
var stream:FileStream = new FileStream();
stream.open( file , FileMode.WRITE );
stream.writeBytes( bytes );
stream.close();
var loadZip:Function = function( event:FZipEvent ):void
{
var zip:FZipFile = event.file;
if ( zip.sizeUncompressed != 0 )
{
var fileData:Object = {};
var file:File = outputFile.resolvePath( zip.filename );
var stream:FileStream = new FileStream();
file.preventBackup = true;
stream.open( file, FileMode.WRITE );
stream.writeBytes( zip.content );
stream.close();
}
};
var inputFile:File = File.applicationStorageDirectory.resolvePath( "ZIP.zip" );
var outputFile:File = File.applicationStorageDirectory.resolvePath( "folderZip" );
var zipFileBytes:ByteArray = event.target.data as ByteArray;
stream = new FileStream();
stream.open( inputFile , FileMode.READ );
stream.readBytes( zipFileBytes );
stream.close();
var zip:FZip = new FZip();
zip.addEventListener( FZipEvent.FILE_LOADED , loadZip );
zip.load( new URLRequest( inputFile.nativePath ) );
}
I don't really expect a total solution but, if you have encountered a similar problem, I'll be thankfull to know what you've done to resolve it.
Thanks a lot

AS3 won't send POST data to browser - wrong URLRequestHeader content type?

I have the following code in my AS3 Flash code that takes a screenshot within the swf using JPGEncoder and sends it to the url where i write it to a file in PHP.
I did run into the Google Chrome Pepperflash issue recently where the function just stops and the page fails to redirect. Nothing gets sent to save.php. By changing
var header:URLRequestHeader = new URLRequestHeader ("Content-type", "application/octet-stream");
to
var header:URLRequestHeader = new URLRequestHeader ("Content-type", "text/plain");
That seemed to do the trick. As of today though this works in internet Explorer but no longer in Chrome, Safari, Firefox. I saw that Adobe put out an update/patch to flash and flash player yesterday - could that have anything to do with it?
If i remove the following:
var header:URLRequestHeader = new URLRequestHeader ("Content-type", "text/plain");
jpgURLRequest.requestHeaders.push(header);
Then the page successfully redirects but $GLOBALS['HTTP_RAW_POST_DATA'] is then empty so no image file can be created.
Is there an alternative header i can put that will solve this?
My code is:
AS3:
function createJPG(m:MovieClip, q:Number, fileName:String) {
var jpgSource:BitmapData = new BitmapData(stage.stageWidth, stage.stageHeight);
jpgSource.draw(stage);
var jpgScreenshot: BitmapData = new BitmapData(362, 310);
jpgScreenshot.copyPixels(jpgSource, new Rectangle(288, 89, 362, 310), new Point(0, 0));
var jpgEncoder:JPGEncoder = new JPGEncoder(q);
var jpgStream:ByteArray = jpgEncoder.encode(jpgScreenshot);
var header:URLRequestHeader = new URLRequestHeader ("Content-type", "text/plain");
var jpgURLRequest:URLRequest = new URLRequest ("http://www.url.com/save.php");
jpgURLRequest.requestHeaders.push(header);
jpgURLRequest.method = URLRequestMethod.POST;
jpgURLRequest.data = jpgStream;
var jpgURLLoader:URLLoader = new URLLoader();
navigateToURL(jpgURLRequest, "_self");
}
save.php
$imagefile=''.$imageURL.'';
$fp = fopen($imagefile, 'wb');
fwrite($fp, $GLOBALS['HTTP_RAW_POST_DATA']);
fclose($fp);
header('Location: https://www.url.com/your-image.php');
Managed to get this working now with the following code. Liam was correct on the Flash Player issue. Working now by separating saving the image and navigating to the url into 2 differents function:
function createJPG(m:MovieClip, q:Number, fileName:String) {
var jpgSource:BitmapData = new BitmapData(stage.stageWidth, stage.stageHeight);
jpgSource.draw(stage);
var jpgScreenshot: BitmapData = new BitmapData(362, 310);
jpgScreenshot.copyPixels(jpgSource, new Rectangle(288, 89, 362, 310), new Point(0, 0));
var jpgEncoder:JPGEncoder = new JPGEncoder(q);
var jpgStream:ByteArray = jpgEncoder.encode(jpgScreenshot);
var urlLoader:URLLoader = new URLLoader();
var header:URLRequestHeader = new URLRequestHeader("Content-type", "application/octet-stream");
var saveJPG:URLRequest = new URLRequest('http://www.url.com/save_image.php?name=filename';
saveJPG.requestHeaders.push(header);
saveJPG.method = URLRequestMethod.POST;
saveJPG.data = jpgStream;
urlLoader.addEventListener(Event.COMPLETE, goToCheckout);
urlLoader.load(saveJPG);
}
function goToCheckout(e:Event):void{
var url:String = 'http://www.url.com/show_image.php';
var request:URLRequest = new URLRequest(url);
try {
navigateToURL(request, '_self');
} catch (e:Error) {
trace("Error occurred!:");
}
}
save_image.php:
if(isset($GLOBALS["HTTP_RAW_POST_DATA"])){
$jpg = $GLOBALS["HTTP_RAW_POST_DATA"];
$path = "";
$id = $_GET["name"];
$file = $id;
file_put_contents($path.$file, $jpg);
echo "complete";
} else{
// error
}
Flash Player version 13.0.0.214 introduces some key security fixes. Unfortunately it also breaks navigateToUrl() by forbidding the changing of any headers in the request given to navigateToUrl(). This breaks POST requests that need to pass in security/session token headers, or to even change the Content-Type, e.g. to text/xml, etc. as you have done in your example.
Right now, as much as it sucks, our best known workaround is to downgrade clients to 13.0.0.206
Adobe proposes using external interface call as described here: https://forums.adobe.com/message/6396080
it uses JavaScript to replace the POST method
The solution proposed by odd_duck seems simpler though - would be great to see the php code as well.

JPEGencode issue in as3

Here is my code. What I m trying to achieve is to be able to capture an image from the the camera and upload it onto a media server but so far I have not been able to encode it succesfully .Can someone please point me in the right direction.
Here is the code
var imagePromise:MediaPromise = event.data;
imageLoader = new Loader();
imageLoader.contentLoaderInfo.addEventListener( Event.COMPLETE, asyncImageLoaded );
imageLoader.addEventListener( IOErrorEvent.IO_ERROR, cameraError );
imageLoader.loadFilePromise( imagePromise );
function asyncImageLoaded(event:Event):void
{
var destination:String = "upload.php";
var now:Date = new Date();
var fileName = "IMG" + now.fullYear + now.month + ".jpg";
var image:Bitmap = Bitmap(imageLoader.content);
var bitmapData:BitmapData = image.bitmapData;
var j = new JPGEncoder(80);
var bytes:ByteArray = j.encode(bitmapData);
}
This is the error I get when i try to encode the image
TypeError: Error #1009: Cannot access a property or method of a null object reference.
which line? 1009 means you're trying to access a variable of something that is NULL. I'm guessing in this case, it's probably the line:
var image:Bitmap = Bitmap(imageLoader.content);
Try adding this:
if (imageLoader.content is Bitmap) {
var image:Bitmap = Bitmap(imageLoader.content);
} else {
throw new Error("What the heck bob?");
}
If it's an error, I bet the content was not decoded properly (which could mean a mime-type that wasn't image/jpg)
Additionally, you could probably use the native jpeg encoder for speed: (flash 11 i believe?)
var byteArray:ByteArray = new ByteArray();
bitmapData.encode(new Rectangle(0,0,640,480), new flash.display.JPEGEncoderOptions(), byteArray);
http://help.adobe.com/en_US/as3/dev/WS4768145595f94108-17913eb4136eaab51c7-8000.html