Flex sending snapshot without using base64Encode - apache-flex

var is:ImageSnapshot = myImagesnapshot;
var str:String = ImageSnapshot.encodeImageAsBase64(is);
As of now, I am sending my jpeg data to the server with the code above.
The problem is that it almost doubles the size of the data.
Is there a way to send the image data directly without using any encoding.

base64 increases size by a third, so if you really have about 100% overhead, you have a problem elsewhere.
haven't looked at the sources to well, but from the reference it seems, you could retrieve the binary data directly.
just tuck that into a URLRequest and send it per POST.

Here is a sample of sending image data without using Base64 :
var myEncoder:JPGEncoder = new JPGEncoder(100);
var byteArray:ByteArray = myEncoder.encode(bitmapData);
var header:URLRequestHeader = new URLRequestHeader("Content-type", "application/octet-stream");
var url:String = "../../default.php";
var saveJPG:URLRequest = new URLRequest(url);
saveJPG.requestHeaders.push(header);
saveJPG.method = URLRequestMethod.POST;
saveJPG.data = byteArray;
On PHP side, I need to access :
$globalS["HTTP_raw_post_data"]

You can save the snapshot as jpg or png.
Take a look at:
http://blog.flexexamples.com/2007/12/07/using-the-imagesnapshot-class-to-capture-images-as-jpegs-or-pngs-in-flex-3/

Related

Is there a cross-platform solution to ImageSource to byte[]?

I did researches and fell on this solution: http://forums.xamarin.com/discussion/22682/is-there-a-way-to-turn-an-imagesource-into-a-byte-array
Initial question: http://forums.xamarin.com/discussion/29569/is-there-a-cross-platform-solution-to-imagesource-to-byte#latest
We want to upload an image through a HTTP Post, here's what we tried:
HttpClient httpClient = new HttpClient ();
byte[] TargetImageByte = **TargetImageSource**; //How to convert it to a byte[]?
HttpContent httpContent = new ByteArrayContent (TargetImageByte);
httpClient.PostAsync ("https://api.magikweb.ca/debug/file.php", httpContent);
We also are having a hard time with the libraries we gotta include in the using clauses. It seems like using System.IO; works, but it doesn't give us access to classes like FileInfo or FileStream.
Anybody has any idea how this can be done aside from custom platform-specific converters?
Possibly a Xamarin.Forms.ImageSource function toByte()?
Lemme know if you need more information.
TargetImageSource is a Xamarin.Forms.ImageSource.
ImageSource TargetImageSource = null;
Solution (Sten was right)
The ImageSource has to originate from another type to exist, that previous type can be converted to a byte[]. In this case, I use the Xamarin.Forms.Labs to take a picture and it returns a MediaFile in which a FileStream is accessible through the Source property.
//--Upload image
//Initialization
HttpClient httpClient = new HttpClient ();
MultipartFormDataContent formContent = new MultipartFormDataContent ();
//Convert the Stream into byte[]
byte[] TargetImageByte = ReadFully(mediaFile.Source);
HttpContent httpContent = new ByteArrayContent (TargetImageByte);
formContent.Add (httpContent, "image", "image.jpg");
//Send it!
await httpClient.PostAsync ("https://api.magikweb.ca/xxx.php", formContent);
App.RootPage.NavigateTo (new ClaimHistoryPage());
The function:
public static byte[] ReadFully(Stream input)
{
using (MemoryStream ms = new MemoryStream()){
input.CopyTo(ms);
return ms.ToArray();
}
}
I think you're looking at it a bit backwards.
ImageSource is a way to provide a source image for Xamarin.Forms.Image to show some content. If you're already showing something on the screen your Image view was populated with data that came from elsewhere, such as a file or resource or stored in an array in memory... or however else you got that in the first place. Instead of trying to get that data back from ImageSource you can keep a reference to it and upload it as needed.
Maybe you can elaborate a bit on your particular need if you don't feel this solution applies to your case.
Pseudo code:
ShowImage(){
ImageSource imageSource = ImageSource.FromFile("image.png"); // read an image file
xf_Image.Source = imageSource; // show it in your UI
}
UploadImage(){
byte[] data = File.ReadAll("image.png");
// rather than
// byte[] data = SomeMagicalMethod(xf_Image.Source);
HttpClient.Post(url, data);
}
UPDATE:
Since you're taking a picture you can copy the MediaFile.Source stream into a memory stream, then you can reset the memory stream's position to point at the beginning of the stream so that you can read it once again and copy it to the http body.
Alternatively you can store the MediaFile.Source to a file and use ImageSource.FromFile to load it in the UI, and when necessary - you can copy the file's contents into an http post body.

Is it possible to load a local file without having to ask the user to browse to it first in an AIR Application?

I'm writing a small application for myself and instead of using a database I'd like to just use Excel to store the small amount of data I have on my local file system. I want to be able to load that data without having to use the typical FileReference browse() method as it would just be annoying to do every time I use the application.
The code below seems to find the file fine as the file.exists method below and most of the other attributes seem to be correct but the file.data is always null.
I'm guessing this is a security issue and that's why I'm running into this problem but I thought I'd ask and see if there is in fact a way around this problem.
var file:File = new File(fullPath + "\\" + currentFolder + ".txt");
if(file.exists) {
var byteArray:ByteArray = file.data;
}
If you want to read the content of a file, use the following code:
var stream:FileStream = new FileStream();
stream.open("some path here", FileMode.READ);
var fileData:String = stream.readUTFBytes(stream.bytesAvailable);
trace(fileData);
The data property is inherited from FileReference class and it will be populated only after a load call (see this link).
You're close, you just need to combine that with a FileStream object
var fileStream:FileStream = new FileStream();
fileStream.open(file, FileMode.READ);
var str:String = fileStream.readMultiByte(file.size, File.systemCharset);
trace(str);
more info here

Flex cachy problem

I am querying to server through flex,first time its show the result but when I insert a new record and query next time,its shows previous results only(problem facing in IE but not in chrome).
You can parametrize your http(?) request, and by setting an always changing parameter, you can make sure that your response never gets read from cache.
In the examples below I use a parameter with the name nocache for this task:
You can set the nocache parameter in your url string:
var url:String = "http://data.your.server?nocache=" + new Date().getTime();
Or -if you use a URLRequest, you can set it inside its data member:
//the url from where you get the data
var url:String = "http://data.your.server";
var urlVars:URLVariables = new URLVariables();
urlVars.nocache = new Date().getTime();
//set the other parameters (if any)
//attach the parameter list to your request
var request:URLRequest = new URLRequest(url);
request.data = urlVars;
Update
Here the new Date().getTime() will return the system's current time in milliseconds, so this way you can be sure, that it won't get called with this parameter value again.
That's because IE caches your request.
Add a random query string parameter to the remote URL you use, like http://myserver.com/fetch_data?random=4234324
(And by random I don't mean use 4234324 all the time, use actionscript to generate a random number and append it to the url)
See this KB from adobe

Converting a flex component w/images to bitmap

I am trying to take images I am placing in a flex canvas component to a bitmap. I was able to get to the point where I'm not getting an error but then no image shows up and the image I save out as a jpg is blank. I imagine I'm not setting the bitmap data correctly but can't figure out what I am doing wrong.
Here is the code where I am converting it to a bitmap:
var imageSnap:ImageSnapshot = ImageSnapshot.captureImage(_renderPop);
var imageByteArray:ByteArray = imageSnap.data as ByteArray;
var bLoader:Loader = new Loader();
bLoader.loadBytes(imageByteArray);
var bmd:BitmapData = new BitmapData(500,500);
bmd.draw(bLoader);
var imgTest:Image = new Image();
imgTest.source = bmd;
_renderPop.renderCanvas.addChild(imgTest);
var fileRef:FileReference = new FileReference();
fileRef.save(bLoader, 'testImage.jpg');
_renderPop.renderCanvas is where I am placing the images. Anybody see anything wrong?
Your "loader" code is wrong. Just after capturing image you may at once save data with FileReference:
var imageSnap:ImageSnapshot = ImageSnapshot.captureImage(_renderPop);
var fileRef:FileReference = new FileReference();
fileRef.save(imageSnap.data, 'testImage.png');
That imageSnap contains not BitmapData but png image bytes. In order to show image you need to capture BitmapData but not image and create Bitmap from bitmap data:
var bmd:BitmapData = ImageSnapshot.captureBitmapData(_renderPop);
var imgTest:Image = new Image();
imgTest.source = new Bitmap(bmd);
_renderPop.renderCanvas.addChild(imgTest);
In result locally testImage.png is created on file system and it is shown in canvas. If you need jpg you should specify:
var imageSnap:ImageSnapshot = ImageSnapshot.captureImage(_renderPop, 0, new JPEGEncoder());
In your code:
var bLoader:Loader = new Loader();
bLoader.loadBytes(imageByteArray);
...you're assuming that the bytes are being loaded immediately; try putting an event listener on the loader as follows:
bLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, completeHandler);
private function completeHandler(event:Event):void
{
// ... the rest of your code goes here
}
The loadBytes functions works like the load function in that they are both asynchronous processes so you'll need the event listener. It is a little counter-intuitive, and i've made the same mistake myself several times.
If that doesn't work, maybe leave out the contentLoaderInfo property, but the above should work...
Let me know if you come right :)

Downloading data posted to server as a file from Flex

This should be trivial, and I'm pretty sure I did it once before.
I'm trying to post data up to a server and have it bounced back to me as a file download, prompting the native browser file download box. I know the server part works just fine becasue I can post from a demo web form, but when I run the following Flex 3 code, I can't even get the request to fire.
var fileRef:FileReference = new FileReference();
private function saveXmlAsFile(event:MouseEvent):void
{
var fileRequest:URLRequest = new URLRequest();
fileRequest.method = URLRequestMethod.POST;
fileRequest.url = "http://foo.com/dataBounce";
var urlVariables:URLVariables = new URLVariables();
urlVariables.content = "Test content to return" ;
// fileRequest.contentType = "application/x-www-form-urlencoded ";
urlVariables.fileName = "test.xml";
fileRef.addEventListener(SecurityEvent.ALL, onSecurityError);
fileRef.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onSecurityError2);
fileRef.addEventListener(IOErrorEvent.NETWORK_ERROR, onNetworkError);
fileRef.addEventListener(Event.COMPLETE, onComplete);
try
{
fileRef.download(fileRequest, "test.xml");
}catch(error:Error) {
model.logger.error("unable to download file");
}
}
Note, when the call to fileRef.download is called, I can't see any request being made across the network using the traditional Firebug or HTTPWatch browser tools.
EDIT: I should add that this is for < Flash Player 10, so I can't use the newer direct save as file functionality.
Any suggestions? Thanks.
You need to add fileRef.upload to trigger the upload.
Also I would move the download statement to the onComplete so the file isn't requested before it's been uploaded.
Your explanation is pretty clear, but when I look at your code, I'm feel like I'm missing something.
The code looks like you're trying to do half of the upload part and half of the download part.
I think the code you currently have posted would work to trigger a download if you set the .method value to GET. I believe you will also need to include the filename as part of the .url property.
However, to post something and then trigger a download of it, you need two separate operations - the operation to post the data and then an operation to download it, which should probably be called from the upload operation's onComplete handler.
OK, I believe I figured out one of the things that's going on.
When you don't set the URLRequest.data property, it defaults the request method to "GET".
So, the working code looks like, with the data set to the posted URL variables:
private var fileRef:FileReference;
private function saveRawHierarchy(event:MouseEvent):void
{
var fileRequest:URLRequest = new URLRequest();
fileRequest.method = URLRequestMethod.POST;
fileRequest.url = "http://foo/bounceback";
var urlVariables:URLVariables = new URLVariables();
urlVariables.content = "CONTENT HERE";
urlVariables.fileName = "newFileName.xml";
fileRequest.data = urlVariables;
fileRef = new FileReference();
fileRef.addEventListener(Event.COMPLETE, onComplete);
try
{
fileRef.download(fileRequest, "appHierarchies.xml");
}catch(error:Error) {
model.logger.error("unable to download file");
}
}
Not sure what was wrong about the request not being made before, though.

Resources