base64 encoded PNG to Blob - blob

I am fiddling around with creating a Blob out of a base64 encoded PNG...
final FormData formData = new FormData();
final String base64Image = "data:image/png;base64,iVBORw0K<reduced the data.....>gg==";
final Blob blob = new Blob([base64Image],"image/png");
formData.append('file', blob, "android.png");
req.send(formData);
I don't know what I a doing wrong but the contents of blob is something but not the png I would like it to be.
thx in advance...
[Update]
final FormData formData = new FormData();
final String base64Image = "iVBORw0KGgo<...reduce data...>kJggg==";
// BTW: I used the Base64 from dart-sdk/io/base64.dart
final List<int> intList = Base64.decode(base64Image);
final Int8Array int8array = new Int8Array.fromList(intList);
final String atobString = window.atob(base64Image);
// Does not work
// final Blob blob = new Blob([atobString]);
// The same...
// final Blob blob = new Blob([int8array]);
formData.append('file', blob, "android.png");
//formData.append('new-filename', "icon-share.png");
req.send(formData);
I think the number of bytes generated by Base64.decode are OK. The filesize was 1003 bytes and decoding also produces 1003 bytes.
[Update 2]
Here is the source I am talking about:
https://github.com/MikeMitterer/AndroidIconGenerator.DART/blob/master/test/src/restserver.dart

OK, here is the answer to my own question:
import 'dart:convert'
...
test(' -> Upload File to REST-Server', () {
final HttpRequest req = new HttpRequest();
loadEnd(HttpRequest request) {
if (request.readyState == HttpRequest.DONE) {
switch(request.status) {
case HttpStatus.HTTP_200_OK:
expect(response['path'].endsWith("android.png"),true);
break;
case HttpStatus.HTTP_0_COMMUNICATION_FAILED:
expect(request.status,HttpStatus.HTTP_200_OK);
break;
default:
expect(request.status,HttpStatus.HTTP_200_OK);
break;
}
}
}
req.open("POST", uriprovider.forUpload().toString());
// REST returns JSON Data
req.setRequestHeader('Accept', 'application/json');
req.onLoadEnd.listen(expectAsync1((ProgressEvent e) => loadEnd(req)));
final FormData formData = new FormData();
final String base64Image = "data:image/png;base64,iVBORw0KG<code reduce for sample>RU5ErkJggg==";
final String raw = "iVBORw0KG<code reduce for sample>RU5ErkJggg==";
final String contenttype = "image/png";
// Base64 is a modified version of dart-sdk/lib/io/base64.dart
final List<int> intList = BASE64.decode(raw);
final Int8Array int8array = new Int8Array.fromList(intList);
// Converting to Uint8Array brought the solution!
final Uint8Array uint8array = new Uint8Array(intList.length);
// does not work!
//var binary = window.atob(raw);
final Blob blob = new Blob([uint8array]);
formData.append('file', blob, "android.png");
req.send(formData);
});
Thanks to everyone pushing me in the right direction!

Need decode base64 (i.e. atob) url, before you encode to Blob. It's easy! Try it!

Related

CloudBlockBlob DownloadTextAsync Behavior Difference

I am using an azure function with event grid trigger and CloudBlockBlob as input binding. The content is getting downloaded from CloudBlockBob using DownloadTextAsync(AccessCondition accessCondition, BlobRequestOptions options, OperationContext operationContext)
If the file being downloaded above is being generated using XmlDocument, DownloadTextAsync returns gibberish. However, if the file is generated by using FileStream, it works fine. PFB the implementations of generating the file-
Using XmlDocument
var stringwriter = new System.IO.StringWriter();
var serializer = new XmlSerializer(typeof(List<ContractName>), new XmlRootAttribute("RootAttributeName"));
serializer.Serialize(stringwriter, contractData);
var xmlString = stringwriter.ToString();
XmlDocument doc = new XmlDocument();
doc.LoadXml(xmlString);
doc.PreserveWhitespace = true;
doc.Save(fileName);
Using FileStream
var serializer = new XmlSerializer(typeof(List<ContractName>), new XmlRootAttribute("RootAttributeName"));
var file = new FileStream(fileName, FileMode.OpenOrCreate);
serializer.Serialize(file, contractData);
file.Close();
Code being used to download the content-
Using DownloadTextAsync
private static async System.Threading.Tasks.Task<string> DownloadContentAsync_DownloadTextAsync(string storageAccountConnectionString, string containerName, string blobName)
{
CloudBlobContainer container = GetContainer(storageAccountConnectionString, containerName);
ICloudBlob blob = await container.GetBlobReferenceFromServerAsync(blobName);
// Download the blob content
string xmlBlobContent =
await (blob as CloudBlockBlob).DownloadTextAsync(
null,
new BlobRequestOptions { LocationMode = LocationMode.PrimaryThenSecondary },
new OperationContext());
return xmlBlobContent;
}
Using DownloadToStreamAsync
private static async System.Threading.Tasks.Task<string> DownloadContentAsync_DownloadToStreamAsync(string storageAccountConnectionString, string containerName, string blobName)
{
CloudBlobContainer container = GetContainer(storageAccountConnectionString, containerName);
ICloudBlob blob = await container.GetBlobReferenceFromServerAsync(blobName);
// Download the blob content
MemoryStream resultStream = new MemoryStream();
await (blob as CloudBlockBlob).DownloadToStreamAsync(
resultStream,
null,
new BlobRequestOptions { LocationMode = LocationMode.PrimaryThenSecondary },
new OperationContext());
string xmlBlobContent = System.Text.Encoding.UTF8.GetString(resultStream.ToArray());
return xmlBlobContent;
}
Why there is a difference in response from DownloadTextAsync.
Updated 0713:
Figured it out. The root cause is that when you're using XmlDocument to generate the xml file, the encoding is utf-16. But for FileStream, it generates the xml file with encoding utf-8.
So, the solution is that, when using XmlDocument, we can specify the encoding to utf-8(no code change for FileStream). Sample code as below:
Generate xml file using XmlDocument:
//2. Using XMLDoc
serializer.Serialize(stringwriter, contractData);
var xmlString = stringwriter.ToString();
XmlDocument doc = new XmlDocument();
doc.LoadXml(xmlString);
doc.PreserveWhitespace = true;
string fileName = String.Format(#"C:\TestBlobDownloadContent\UsingXMLDoc" + count + ".xml");
//encoding as utf-8
using (TextWriter sw = new StreamWriter(fileName, false, Encoding.UTF8))
{
doc.Save(sw);
}
When read the xml file from blob storage via DownloadTextAsync() method, no need to specify the encoding option, like below:
// Download the blob content
string xmlBlobContent =
await (blob as CloudBlockBlob).DownloadTextAsync(
null,
new BlobRequestOptions { LocationMode = LocationMode.PrimaryThenSecondary },
new OperationContext());
Original answer:
This is due to the encode/decode issue.
Solution:
In the DownloadTextAsync() method, add parameter System.Text.Encoding.Unicode. Like below:
string xmlBlobContent =
await (blob as CloudBlockBlob).DownloadTextAsync(
System.Text.Encoding.Unicode,
null,
new BlobRequestOptions { LocationMode = LocationMode.PrimaryThenSecondary },
new OperationContext());
The test result:

Posting GZip content using RestSharp

How do I post GZip data using RestSharp. I have the following code but it isn't working as I would expect:
var restRequest = new RestRequest(url, Method.POST)
{
Timeout = Constants.DefaultTimeoutMilliseconds
};
var dataStream = new MemoryStream();
using (var zipStream = new GZipStream(dataStream, CompressionMode.Compress))
{
using (var writer = new StreamWriter(zipStream))
{
writer.Write(new DotNetXmlSerializer().Serialize(content));
}
}
var compressedBytes = dataStream.ToArray();
restRequest.AddParameter("application/x-gzip", compressedBytes, ParameterType.RequestBody);
return _restClient.Execute<TResponseData>(restRequest);
When I run this and check the wireshark trace, the compressedBytes variable is posted as
'System.Byte[]' - as if ToString() has been called on it despite the parameter being a system.object.
If I pass the compressed byte array through as a string using both Convert.ToBase64String() and Encoding.Utf8.GetString() then I am unable to decompress the GZip at the server. I simply get 'System.IO.InvalidDataException: The magic number in GZip header is not correct. Make sure you are passing in a GZip'.
Is there any way of posting Gzipped data using RestSharp?
Make sure you've updated to the latest version of RestSharp (like 104.4.0) as this was a bug in a previous version.
I think this was fixed in 104.2 where the PUT or POST of binary data ended up with the System.Byte[] being represented as the string.
Update your NuGet reference and try it again. Good luck!
var body = "some string";
var dataStream = new MemoryStream();
byte[] dataToCompress = Encoding.UTF8.GetBytes(body);
using (var memoryStream = new MemoryStream())
{
using (var gzipStream = new GZipStream(memoryStream, CompressionLevel.Optimal))
{
gzipStream.Write(dataToCompress, 0, dataToCompress.Length);
}
dataStream = memoryStream;
}
var client = new RestClient("url");
var request = new RestRequest("", Method.POST);
var compressedBytes = dataStream.ToArray();
request.AddHeader("Content-Encoding", "gzip");
request.AddParameter("application/x-gzip", compressedBytes, ParameterType.RequestBody);
//client.RemoteCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true;
IRestResponse response = await client.ExecuteAsync(request);
Console.WriteLine(response.Content);

WinRT No mapping for the Unicode character exists in the target multi-byte code page

I am trying to read a file in my Windows 8 Store App. Here is a fragment of code I use to achieve this:
if(file != null)
{
var stream = await file.OpenAsync(FileAccessMode.Read);
var size = stream.Size;
using(var inputStream = stream.GetInputStreamAt(0))
{
DataReader dataReader = new DataReader(inputStream);
uint numbytes = await dataReader.LoadAsync((uint)size);
string text = dataReader.ReadString(numbytes);
}
}
However, an exeption is thrown at line:
string text = dataReader.ReadString(numbytes);
Exeption message:
No mapping for the Unicode character exists in the target multi-byte code page.
How do I get by this?
I managed to read file correctly using similar approach to suggested by duDE:
if(file != null)
{
IBuffer buffer = await FileIO.ReadBufferAsync(file);
DataReader reader = DataReader.FromBuffer(buffer);
byte[] fileContent = new byte[reader.UnconsumedBufferLength];
reader.ReadBytes(fileContent);
string text = Encoding.UTF8.GetString(fileContent, 0, fileContent.Length);
}
Can somebody please elaborate, why my initial approach didn't work?
Try this instead of string text = dataReader.ReadString(numbytes):
dataReader.ReadBytes(stream);
string text = Convert.ToBase64String(stream);
If, like me, this was the top result when search for the same error regarding UWP, see the below:
The code I had which was throwing the error (no mapping for the unicode character exists..):
var storageFile = await Windows.Storage.AccessCache.StorageApplicationPermissions.FutureAccessList.GetFileAsync(fileToken);
using (var stream = await storageFile.OpenAsync(FileAccessMode.Read))
{
using (var dataReader = new DataReader(stream))
{
await dataReader.LoadAsync((uint)stream.Size);
var json = dataReader.ReadString((uint)stream.Size);
return JsonConvert.DeserializeObject<T>(json);
}
}
What I changed it to so that it works correctly
var storageFile = await Windows.Storage.AccessCache.StorageApplicationPermissions.FutureAccessList.GetFileAsync(fileToken);
using (var stream = await storageFile.OpenAsync(FileAccessMode.Read))
{
T data = default(T);
using (StreamReader astream = new StreamReader(stream.AsStreamForRead()))
using (JsonTextReader reader = new JsonTextReader(astream))
{
JsonSerializer serializer = new JsonSerializer();
data = (T)serializer.Deserialize(reader, typeof(T));
}
return data;
}

How to display Windows.Graphics.Imaging.BitmapDecoder in WinJS?

I am trying to make an app that applies filter effects on images. From FilePicker I can get a IRandomAccessStream and I can convert it to BitmapDecoder. But I am not sure how to diplay the bitmap data as image? I do not want to use the file name or path, just want to display the BitmapData as an image. What control should I use in WinJS and how to do it?
Convert an IInputStream or IRandomAccessStream to an image with MSApp.createStreamFromInputStream() and URL.createObjectURL():
var path = Windows.Storage.ApplicationData.current.localFolder.path + "\\thing.jpg";
Windows.Storage.StorageFile.getFileFromPathAsync(path).then(function (file) {
file.openAsync(Windows.Storage.FileAccessMode.read).then(function (randomStream) {
// Convert the stream to MS-Stream.
var msStream = MSApp.createStreamFromInputStream("image/jpeg", randomStream);
var imageUrl = URL.createObjectURL(msStream);
var img = document.getElementById("theImage");
img.src = imageUrl;
}, onError);
}, onError);
The HTML should look like this:
<img id="theImage" src="#" />
These MSDN blogs explain the following process in more detail
http://goo.gl/izCdf
http://goo.gl/OLgfn
I found a way to create a BitmapEncoder from a BitmapDecoder. That encoder can be used to create a in memory stream that can be displayed in a field.
internal async Task<InMemoryRandomAccessStream> applyFilterInternal()
{
inputStream = await file.OpenAsync(Windows.Storage.FileAccessMode.ReadWrite);
decoder = await Windows.Graphics.Imaging.BitmapDecoder.CreateAsync(inputStream);
var memStream = new Windows.Storage.Streams.InMemoryRandomAccessStream();
var encoder = await Windows.Graphics.Imaging.BitmapEncoder.CreateForTranscodingAsync(memStream, decoder);
encoder.BitmapTransform.ScaledWidth = 640;
encoder.BitmapTransform.ScaledHeight = 480;
encoder.BitmapTransform.Rotation = Windows.Graphics.Imaging.BitmapRotation.Clockwise90Degrees;
// Fant is a relatively high quality interpolation algorithm.
encoder.BitmapTransform.InterpolationMode = Windows.Graphics.Imaging.BitmapInterpolationMode.Fant;
// Attempt to generate a new thumbnail from the updated pixel data.
// Note: Only JPEG, TIFF and JPEG-XR images support encoding thumbnails.
encoder.IsThumbnailGenerated = true;
await encoder.FlushAsync();
return memStream;
}
public IAsyncOperation<InMemoryRandomAccessStream> applyFilter()
{
Task<InMemoryRandomAccessStream> from = applyFilterInternal();
IAsyncOperation<InMemoryRandomAccessStream> to = from.AsAsyncOperation();
return to;
}
To display this -
filter.applyFilter().then(function (memStream) {
var msStream = MSApp.createStreamFromInputStream("image/jpeg", memStream);
var imageURL = URL.createObjectURL(msStream);
id("imageInput").src = imageURL;
});

Encoding with HttpClient

I am using the HttpClient class in Windows 8. With Windows Phone, I use
the WebClient class in combination with encoding to get the right encoding.
WebClient xml = new WebClient();
xml.Encoding = Encoding.GetEncoding("ISO-8859-1");
In Windows 8 it is looks like this:
HttpClient xml = new HttpClient();
HttpResponseMessage response = await xml.GetAsync(uri);
responsetext = await response.Content.ReadAsStringAsync();
How can I add a encoding to support German (umlaute)?
I don't have time to test right now, but have you tried using the HttpContent.ReadAsByteArrayAsync method (rather than ReadAsStringAsync) and encoding the resulting byte[] into ISO-8859-1 separately?
Change ReadAsStringAsync to ReadAsBufferAsync and parse result with required encoding
var buffer = await response.Content.ReadAsBufferAsync();
byte [] rawBytes = new byte[buffer.Length];
using (var reader = DataReader.FromBuffer(buffer))
{
reader.ReadBytes(rawBytes);
}
var res = Encoding.UTF8.GetString(rawBytes, 0, rawBytes.Length);