0

How to make a picture from a base64-string to send it to server by using HttpRequest.request?

For example, I have the following base64-string:

'data:image/jpeg;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=='

Instead of sending it I would like to post a jpeg to server? Is it possible?

Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
Roman
  • 2,145
  • 4
  • 26
  • 33
  • 1
    Why not send it as a base64 string and convert it serverside? – Johan Mar 05 '14 at 11:37
  • in order to decrease the server loading – Roman Mar 05 '14 at 11:42
  • https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Sending_and_Receiving_Binary_Data – Johan Mar 05 '14 at 11:43
  • 1
    You don't need any conversion library, you can just put in base64 data as source, look at this question: http://stackoverflow.com/questions/4409445/base64-png-data-to-html5-canvas – Daniel W. Mar 05 '14 at 12:02

3 Answers3

2

Convert Base64 to bytes
How to native convert string -> base64 and base64 -> string

Upload binary as image
Dart how to upload image
EDIT
(this is the server part, I have to look for the client part)

Client code:

  var request = new HttpRequest()
    ..open("POST", 'http://yourdomain.com/yourservice')
    ..overrideMimeType("image/your-imagetype") // might be that this doesn't work than use the next line
    ..setRequestHeader("Content-Type", "image/your-imagetype")
    ..onProgress.listen((e) => ...);

  request
    ..onReadyStateChange.listen((e) => ...)
    ..onLoad.listen((e) => ...)
    ..send(yourBinaryDataAsUint8List);

Convert to image:
I think you need to create a dataURL like show here How to upload a file in Dart?
and then use the created dataUrl as src in code like shown here How to load an image in Dart
see also Base64 png data to html5 canvas as @DanFromGermany mentioned in his comment on the question.

It may be necessary to convert List to Uint8List in between.
Please add a comment if you need more information.

Community
  • 1
  • 1
Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • Thanks for help! I hope there is a way to make a picture on client side! – Roman Mar 05 '14 at 11:55
  • To display it on the client? – Günter Zöchbauer Mar 05 '14 at 11:59
  • Yes, the picures will be displayed on the client. I know that I can use something like img.src="data:image/png;base64,iVBORw0KGgoAAAANSUhEU... But this way is not optimal for storing images on server. – Roman Mar 05 '14 at 12:12
  • I think you should make more clear what you actually want. Do you want to send it to the server? Why?. Why do you have base64? Where did you get it in this format? What format do you want on the server? – Günter Zöchbauer Mar 05 '14 at 12:15
  • I would like to upload images on the server. All images are resized on client as here https://code.google.com/p/dart-examples/source/browse/examples/DartExamples/ImageScaling/ImageScaling.dart. This code produce a base64 string. But the storing base64 leads to overheads on the server.. (Base64-encoded Data URLs are 33% larger in size than their binary counterparts) – Roman Mar 05 '14 at 12:31
  • 1
    I think you should have all information then. Have you? It seems canvas can create create JPEG. This probably looks similar in Dart http://stackoverflow.com/questions/18419246 (even resize http://stackoverflow.com/questions/2303690) never tried it myself though. – Günter Zöchbauer Mar 05 '14 at 12:41
1

I like decoding on server-side, but anyways.

Basically you just split a text you got from canvas.toDataUrl(), convert the Base64 text to binary data, then send it to server. Use "CryptoUtils" in "crypto" library to treat Base64. I haven't tested with any proper http server, but this code should work.

// Draw an on-memory image.
final CanvasElement canvas = document.createElement('canvas');
canvas.width = 256;
canvas.height = 256;
final CanvasRenderingContext2D context = canvas.getContext('2d');
final CanvasGradient gradient = context.createLinearGradient(0, 0, 0, canvas.height);
gradient.addColorStop(0, "#1e4877");
gradient.addColorStop(0.5, "#4584b4");
context.fillStyle = gradient;
context.fillRect(0, 0, canvas.width, canvas.height);
context.beginPath();
context.moveTo(10, 10);
context.lineTo(240, 240);
context.lineWidth = 10;
context.strokeStyle = '#ff0000';
context.stroke();

// Convert the image to data url
final String dataUrl = canvas.toDataUrl('image/jpeg');
final String base64Text = dataUrl.split(',')[1];
final Uint8ClampedList base64Data = new Uint8ClampedList.fromList(
    CryptoUtils.base64StringToBytes(base64Text));

// Now send the base64 encoded data to the server.
final HttpRequest request = new HttpRequest();
request
  ..open("POST", 'http://yourdomain.com/postservice')
  ..onReadyStateChange.listen((_) {
    if (request.readyState == HttpRequest.DONE &&
        (request.status == 200 || request.status == 0)) {
      // data saved OK.
      print("onReadyStateChange: " + request.responseText); // output the response from the server
    }
  })
  ..onError.listen((_) {
    print("onError: " + _.toString());
  })
  ..send(base64Data);

I posted a complete snippet here. https://gist.github.com/hyamamoto/9391477

1

I found the Blob conversion part not to be working (anymore?). The code from here does work:

Blob createImageBlob(String dataUri) {
  String byteString = window.atob(dataUri.split(',')[1]);
  String mimeString = dataUri.split(',')[0].split(':')[1].split(';')[0];
  Uint8List arrayBuffer = new Uint8List(byteString.length);
  Uint8List dataArray = new Uint8List.view(arrayBuffer.buffer);
  for (var i = 0; i < byteString.length; i++) {
    dataArray[i] = byteString.codeUnitAt(i);
  }
  Blob blob = new Blob([arrayBuffer], mimeString);
  return blob;
}
Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567