what's the difference between Blob and Blobbuilder or Blobbuilder's issue on android native browser
Asked Answered
U

2

8

The question is not duplicate from What's the difference between BlobBuilder and the new Blob constructor?

I'm doing web app. To upload image I use Blob, just in case BlobBuilder too. Blob works well, but Blob doesn't work on android native browser, android native browser uses BlobBuilder. I expected, Blob and BlobBuilder returns the same blob, but they didn't. Here is my code:

base64toBlob: function(b64Data, contentType, sliceSize) {
  var BlobBuilder, blob, byteArray, byteCharacters, byteNumbers, charCodeFromCharacter, err, posIndex;

  if (contentType == null) {
    contentType = '';
  }
  if (sliceSize == null) {
    sliceSize = 1024;
  }
  posIndex = b64Data.indexOf('base64,');
  if (posIndex !== -1) {
    b64Data = b64Data.substring(posIndex + 7);
  }
  charCodeFromCharacter = function(c) {
    return c.charCodeAt(0);
  };
  byteCharacters = atob(b64Data.replace(/\s/g, ''));
  byteNumbers = Array.prototype.map.call(byteCharacters, charCodeFromCharacter);
  byteArray = new Uint8Array(byteNumbers);
  try {
    blob = new Blob([byteArray.buffer], {
      type: contentType
    });
    return blob;
  } catch (_error) {
    err = _error;
    BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder;
    blob = new BlobBuilder();
    blob.append(byteArray.buffer);
    return blob.getBlob(contentType);
  }
}

I did logs when I send request

blobImg = base64toBlob(base64Data, imageType);
alert(JSON.stringify(blobImg));
// alert shows {"type": "image/jpeg", "size": 10251 } when blob worked
// alert shows {"type": "image/jpeg", "size": 27822 } when blobbuilder worked
ajaxRequest.send(blobImg);

I tried to upload at the same image on all browsers. On Chrome and other browsers I get from log {"type": "image/jpeg", "size": 10251 } and request send successfully, but on android native browser i get {"type": "image/jpeg", "size": 27822 } and request failed with status code 0. On android browser works catch part (I guess, it means Android native browser does not support Blob) I tested in android 4.1.2. I found nothing from google about the issue. I will glad If somebody help me!

Unweighed answered 28/12, 2013 at 6:59 Comment(2)
I have same issue.Do you have any idea how to solve this?A workaround is also acceptable.Appreciated in advanced.Contemporize
@ablian, I created an answerLenten
S
4

Note the difference between what you pass in:

try {
    blob = new Blob([byteArray.buffer], { // use of .buffer
      type: contentType
    });
    return blob;
} catch (_error) {
    err = _error;
    BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder;
    blob = new BlobBuilder();
    blob.append(byteArray); // just uses the raw array
    return blob.getBlob(contentType);
}

From the MDN documentation for BlobBuilder.append:

Appends the contents of the specified JavaScript object to the Blob being built. If the value you specify isn't a Blob, ArrayBuffer, or String, the value is coerced to a string before being appended to the blob.

byteArray is not of type ArrayBuffer, so it's probably being coerced to a string. You can confirm this yourself by converting it to a string and checking its length. To fix it, just use byteArray.buffer in your catch block.

Interestingly enough, the Blob constructor appears to accept an ArrayBufferView directly, which your Uint8Array qualifies as. This may mean you don't actually need the .buffer in that case, though I'm not familiar enough with the API to say with any confidence.

Sarilda answered 28/12, 2013 at 7:17 Comment(1)
Well, that invalidates my entire answer. Please take care and never, ever paraphrase code when asking questions. Providing an answer to a less common question like this one can take a significant time investment, and it's very discouraging to have that effort wasted because the code in the question isn't actually the code that presented an error. Always copy the code directly from the source and run the excerpt if possible.Sarilda
U
2

It works in our case, I don't know, does it work for you.

base64toBlob: (b64Data, contentType = '', needArrBuffer) ->
    posIndex = b64Data.indexOf 'base64,'
    if posIndex isnt -1
        b64Data = b64Data.substring posIndex + 7

    charCodeFromCharacter = ( c ) ->
        c.charCodeAt( 0 )

    byteCharacters = b64Data
    b64Data = b64Data.replace(/\s/g, '')
    try
        byteCharacters = atob?(b64Data)
        byteCharacters ?= Base64.decode(b64Data)
    catch err

    byteNumbers = Array.prototype.map.call(byteCharacters,
            charCodeFromCharacter)
    byteArray = new Uint8Array(byteNumbers)

    try
        new Blob [byteArray.buffer], type: contentType
    catch err
        if needArrBuffer
            # Android browser cannot send Blob by XHR, so we use ArrayBuffer instead of Blob
            return byteArray.buffer
        Util.log 'Warning: No native Blob supported! ' + err.message
        BlobBuilder = window.WebKitBlobBuilder || window.MozBlobBuilder
        blob = new BlobBuilder()
        blob.append(byteArray.buffer)
        blob.getBlob(contentType)


blobImg = base64toBlob(base64Data, imageType, true);
ajaxRequest.send(blobImg);
Unweighed answered 26/5, 2015 at 6:37 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.