I've got XML data in AS3 that needs to be compressed, validated on my Java Google App Engine servlet then saved to a file in Google Cloud Storage. Later that file will be opened and decompressed by the AS3 client. The process works if I do it with plain XML or text, but if I ByteArray#compress the data, it dies during ByteArray#uncompress with "There was an error decompressing the data".
I've tried setting the content type and mime type at various points, as well as encoding with Base64, but every attempt seems to break in a different way and I never get the same XML back that I sent in. Do I need to use multipart? Should I compress on the server? What's the best practice for doing this?
Sending the data from AS3:
// compress xml using zlib
var xml:XML = <contents><thing>value</thing></contents>;
var bytes:ByteArray = new ByteArray();
bytes.writeObject(xml);
bytes.position = 0;
bytes.compress();
var request:URLRequest = new URLRequest(url);
var urlVariables :URLVariables = new URLVariables();
urlVariables.filename = "somefile.bin";
urlVariables.contents = bytes;
request.data = urlVariables;
request.method = URLRequestMethod.POST;
loader = new URLLoader();
loader.load(request);
Receiving it in the Java servlet and creating the file:
public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
String filename = req.getParameter("filename");
byte[] contents = req.getParameter("contents").getBytes();
GSFileOptionsBuilder optionsBuilder = new GSFileOptionsBuilder()
.setBucket("bucketname")
.setKey(filename)
.setAcl("public-read")
.setMimeType("binary/octet-stream");
AppEngineFile writableFile = fileService.createNewGSFile(optionsBuilder.build());
boolean lockForWrite = true;
FileWriteChannel writeChannel = fileService.openWriteChannel(writableFile, lockForWrite);
writeChannel.write(ByteBuffer.wrap(contents));
writeChannel.closeFinally();
}
Opening the new file in AS3:
var url :String = "http://commondatastorage.googleapis.com/bucketname/somefile.bin";
var request:URLRequest = new URLRequest(url);
request.method = URLRequestMethod.GET;
loader = new URLLoader();
loader.addEventListener(Event.COMPLETE, handleComplete);
loader.load(request);
protected function handleComplete (event:Event):void {
var bytes:ByteArray = new ByteArray();
bytes.writeObject(event.target.data);
// dies on this line with "There was an error decompressing the data."
bytes.uncompress();
var xml:XML = new XML(new String(bytes));
trace(xml);
}
Here is the code that I use to save an xml. I send the data to PHP but I would think it would work the same way for you... I haven't had any trouble with it.
var createXMLURL:URLRequest = new URLRequest("createXML.php");
createXMLURL.method = URLRequestMethod.POST;
var Variables:URLVariables = new URLVariables();
Variables.xmlString = xml.toXMLString();
Variables.filename = filename;
createXMLURL.data = Variables;
var loader:URLLoader = new URLLoader();
loader.dataFormat = "VARIABLES";
loader.addEventListener(Event.COMPLETE, xmlCreated);
loader.load(createXMLURL);
Let me know if you have any questions about what some of the variables are since I did not include their declarations (I think they are pretty easy to figure out).
Now this doesn't send that data in binary format like you were asking for, but I don't know why you wouldn't be able to convert the string to binary once you receive it in java if you really need the raw bytes.
I would base64 encode before you POST if from the client, store it that way in a TextProerty, then base64 decode / decompress when received back at the client. If you want to store it as binary on GAE, then base64 decode it into a Blob. Here are some code snippets I pieced together using your code, and something similar I do using HttpService -- apologies in advance for not extensively proofing it. HTH.
private var _serviceHttp:HTTPService = new HTTPService;
private function postBytes():void {
var xml:XML = <contents><thing>value</thing></contents>;
var bytes:ByteArray = new ByteArray();
bytes.writeObject(xml);
bytes.position = 0;
bytes.compress();
var enc:Base64Encoder = new Base64Encoder();
enc.encodeBytes(bytes, 0, bytes.length);
var myObj:Object = new Object();
myObj["bytes"] = enc.toString();
// myObj["other_variables"] = your_other_varaibles;
_serviceHttp.method = "POST";
_serviceHttp.resultFormat = "flashvars";
_serviceHttp.url = your_url_here;
_serviceHttp.addEventListener(ResultEvent.RESULT, urlHandler);
_serviceHttp.addEventListener(FaultEvent.FAULT, urlErrorHandler);
_serviceHttp.send(myObj);
}
Related
Server
Using below code to return byte array ,but not able to get byte array at client side.
byte[] bytes = Encoding.ASCII.GetBytes(getOpenCasesResponse.Content);
var dataStream = new MemoryStream(bytes);
HttpResponseMessage httpResponseMessage = new HttpResponseMessage(HttpStatusCode.OK);
httpResponseMessage.Content = new StreamContent(dataStream);
httpResponseMessage.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment");
// httpResponseMessage.Content.Headers.ContentDisposition.FileName = bookName;
httpResponseMessage.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/octet-stream");
return httpResponseMessage;
Client
Below is code I am trying to call from client to get byte array, but not able to get data from server.
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/octet-stream"));
var s = response.Content.ReadAsStringAsync().Result;
byte[] mybytearray= Encoding.UTF8.GetBytes(s);
I am trying to encode, Image to Base 64 string in AngularJS2
handleFileSelect(evt) {
var files = evt.target.files;
var file = files[0];
if (files && file) {
var reader = new FileReader();
reader.onload = this._handleReaderLoaded.bind(this);
reader.readAsBinaryString(file);
}
}
_handleReaderLoaded(readerEvt) {
var binaryString = readerEvt.target.result;
this.model.UserProfileImageBase64 = btoa(binaryString);
console.log(this.model.UserProfileImage);
}
I am receiving a different string,in compare to encoding it from Java
Base64.encodeToString(getBytesFromBitmap(bitmap),Base64.NO_WRAP);
Any Idea how can we match both Base64 encoding? I had tried same with base64 encoding in angular as well
this.model.UserProfileImageBase64 = Base64.encode(binaryString);
But no dfiference in result.
BtoA and Base64 producing same result and, if I am verifying it online I am getting image as well but I need it in the same format which is generated by Java
I am getting the same result with java and javascript.
With java I did:
byte[] imageBytes = IOUtils.toByteArray(new URL("https://www.w3schools.com/css/paris.jpg"));
String base64 = Base64.getEncoder().encodeToString(imageBytes);
System.out.println(base64);
With javascript I did:
const fileReader: FileReader = new FileReader();
fileReader.readAsDataURL(file);
fileReader.onloadend = () => {
retVal.next(fileReader.result);
};
NOTE: I would suggest not to use readBynaryAsString as it is deprecated and might not work. FileReader
NOTE: That in javascript I wait till the file is uploaded to get the data and I passed to an observable next(...)
changeListener($event) : void {
this.readThis($event.target);
}
readThis(inputValue: any): void {
var file:File = inputValue.files[0];
var myReader:FileReader = new FileReader();
myReader.onloadend = (e) => {
this.image = myReader.result;
}
myReader.readAsDataURL(file);
}
component.html
<input type="file" accept="image/*" (change)="changeListener($event)">
Follow this link Angular 2 encode image to base64
I need to convert the following code from Java to C# when I'm using restAPI in C#.
In java :
HttpGet statusGet = new HttpGet(fileUrl);
statusGet.setHeader("X-API-TOKEN", API_TOKEN);
HttpResponse response = httpClient.execute(statusGet);
// Extract exported file
ZipInputStream zs = new ZipInputStream(response.getEntity().getContent());
In C# this is what I have:
var client1 = new RestClient(fileUrl);
var request1 = new RestRequest(Method.GET);
request1.AddHeader("X-API-TOKEN", "API_TOKEN");
request1.AddHeader("content-type", "application/json");
request1.AddParameter("application/json", "{\n\t\"format\" : \"csv\",\n\t\"surveyId\" : \"_surveyId\"\n}", ParameterType.RequestBody);
IRestResponse responsedata = client1.Execute(request1);
var download=client1.DownloadData(request1);
MemoryStream stream = new MemoryStream(download);
ZipInputStream zs = new ZipInputStream(stream);
using (ZipFile zip1 = ZipFile.Read(zs))
I have no clue how to implement response.getEntity().getContent(). I believe it is getting the Stream(Containing a zip file?)
Updated: So I get the byte array from client1.DownloadData(request1), looks like it is not right to convert it to stream (has readtimeout exception). and it will not be able to read from zipfile.read
Thank you so much for your help
Are you getting any specific errors? It looks like you are implementing this using RestSharp. Have you followed their examples and read through their documentation?
I have not personally used this third-party solution, but immediately on their front page they have the following example that does exactly what you are trying to do:
var client = new RestClient("http://example.com");
// client.Authenticator = new HttpBasicAuthenticator(username, password);
var request = new RestRequest("resource/{id}", Method.POST);
request.AddParameter("name", "value"); // adds to POST or URL querystring based on Method
request.AddUrlSegment("id", "123"); // replaces matching token in request.Resource
// easily add HTTP Headers
request.AddHeader("header", "value");
// add files to upload (works with compatible verbs)
request.AddFile(path);
// execute the request
IRestResponse response = client.Execute(request);
var content = response.Content; // raw content as string
// or automatically deserialize result
// return content type is sniffed but can be explicitly set via RestClient.AddHandler();
RestResponse<Person> response2 = client.Execute<Person>(request);
var name = response2.Data.Name;
// easy async support
client.ExecuteAsync(request, response => {
Console.WriteLine(response.Content);
});
// async with deserialization
var asyncHandle = client.ExecuteAsync<Person>(request, response => {
Console.WriteLine(response.Data.Name);
});
// abort the request on demand
asyncHandle.Abort();
It looks like you would want to access the IRestResponse.Content property, or to deserialize using the RestClient.Execute<T>(RestRequest request) function.
In one of my application i am cropping the image using http://fengyuanchen.github.io/cropper/
The resultant cropped image am getting in the base64 dataURL format, but i required that to be in file object format.
How to convert the dataURL to file either in client side or server side.
Use Blob instead of the deprecated BlobBuilder. The code is very clean and simple. (Manuel Di Iorio's code is deprecated.)
function dataURLtoBlob(dataurl) {
var arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
while(n--){
u8arr[n] = bstr.charCodeAt(n);
}
return new Blob([u8arr], {type:mime});
}
//test:
//var blob = dataURLtoBlob('data:text/plain;base64,YWFhYWFhYQ==');
Data URI scheme
How to convert dataURL to file object in javascript?
function dataURItoBlob(dataURI) {
// convert base64 to raw binary data held in a string
// doesn't handle URLEncoded DataURIs - see SO answer #6850276 for code that does this
var byteString = atob(dataURI.split(',')[1]);
// separate out the mime component
var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];
// write the bytes of the string to an ArrayBuffer
var ab = new ArrayBuffer(byteString.length);
var ia = new Uint8Array(ab);
for (var i = 0; i < byteString.length; i++) {
ia[i] = byteString.charCodeAt(i);
}
// write the ArrayBuffer to a blob, and you're done
var bb = new BlobBuilder();
bb.append(ab);
return bb.getBlob(mimeString);
}
Then just append the blob to a new FormData object and post it to your server using ajax:
var blob = dataURItoBlob(someDataUrl);
var fd = new FormData(document.forms[0]);
var xhr = new XMLHttpRequest();
fd.append("myFile", blob);
xhr.open('POST', '/', true);
xhr.send(fd);
Thats my validation for input.
$data = $_POST['thumb'];
$uriPhp = 'data://' . substr($data, 5);
if ( base64_encode(base64_decode($uriPhp))){
$_POST['thumb'] = $uriPhp;
}
for saving I am using : http://www.verot.net/php_class_upload.htm
$foo = new Upload($_POST['thumb']);
if ($foo->uploaded) {
// save uploaded image with a new name
$foo->file_new_name_body = $name;
$foo->image_convert = 'png';
$foo->Process("uploads/");
}
I am trying to update photo using Google apps engine.I have imageurl i convert it into byte array and then encode
it using base64.i got encoded string,now i m trying to update photodata using directory API Reference
https://developers.google.com/admin-sdk/directory/v1/reference/users/photos#resource
after update i got error invalid byteString.I face this problem from yesterday.So Let me know where i did wrong? Below is my code.
import com.google.appengine.repackaged.org.apache.commons.codec.binary.Base64;
above class used for Base64.
URL url = new URL(myImageUrl);
ByteArrayOutputStream bais = new ByteArrayOutputStream();
InputStream is = null;
try {
is = url.openStream ();
byte[] byteChunk = new byte[4096]; // Or whatever size you want to read in at a time.
int n;
while ( (n = is.read(byteChunk)) > 0 ) {
bais.write(byteChunk, 0, n);
}
System.out.println(byteChunk);
byte[] encoded = Base64.encodeBase64(byteChunk);
String ecodedString = new String(encoded, "UTF-8");
ecodedString = ecodedString.replace("/", "_");
ecodedString = ecodedString.replace("+", "-");
ecodedString = ecodedString.replace("=", "*");
System.out.println(ecodedString);
Padding could be the problem, try not replacing "=" with "*". See also:
Converting string to web-safe Base64 format
p.s. repackaged libs are discouraged in app engine; you may use DatatypeConverter.printBase64Binary() instead.