33

I am developping an application where I recieve image data stored in a uint8Array. I then transform this data to a Blob and then build the image url.

Simplified code to get data from server:

var array;

var req = new XMLHttpRequest();
var url = "img/" + uuid + "_" +segmentNumber+".jpg";
req.open("GET", url, true);
req.responseType = "arraybuffer";
req.onload = function(oEvent) {
    var data = req.response;    
    array = new Int8Array(data);      
};

Constructor:

out = new Blob([data], {type : datatype} );

The Blob contsructor is causing problem. It works fine on all browsers except Chrome on mobile and desktop devices.

Use of Blob:

// Receive Uint8Array using AJAX here
// array = ...
// Create BLOB
var jpeg = new Blob( [array.buffer], {type : "image/jpeg"});
var url = DOMURL.createObjectURL(jpeg);
img.src = url;

Desktop Chrome gives me a warnning : ArrayBuffer values are deprecated in Blob Constructor. Use ArrayBufferView instead.

Mobile Chrome gives me an error: illegal constructor

If I change the constructor to work on Chrome it fails on other browsers.

Jacob
  • 3,580
  • 22
  • 82
  • 146

2 Answers2

29

So, these are actually two different problems. The Desktop Chrome warning was a bug in chrome which is fixed since 2013-03-21.

Mobile Chrome is giving you a TypeError because the blob constructor is not supported. Instead you must use the old BlobBuilder API. The BlobBuilder API has browser specific BlobBuilder constructors. This is the case for FF6 - 12, Chrome 8-19, Mobile Chrome, IE10 and Android 3.0-4.2.

var array = new Int8Array([17, -45.3]);

try{
  var jpeg = new Blob( [array], {type : "image/jpeg"});
}
catch(e){
    // TypeError old chrome and FF
    window.BlobBuilder = window.BlobBuilder || 
                         window.WebKitBlobBuilder || 
                         window.MozBlobBuilder || 
                         window.MSBlobBuilder;
    if(e.name == 'TypeError' && window.BlobBuilder){
        var bb = new BlobBuilder();
        bb.append(array.buffer);
        var jpeg = bb.getBlob("image/jpeg");
    }
    else if(e.name == "InvalidStateError"){
        // InvalidStateError (tested on FF13 WinXP)
        var jpeg = new Blob( [array.buffer], {type : "image/jpeg"});
    }
    else{
        // We're screwed, blob constructor unsupported entirely   
    }
}

Fiddle: http://jsfiddle.net/Jz8U3/13/

jayarjo
  • 16,124
  • 24
  • 94
  • 138
JoeyP
  • 2,622
  • 2
  • 26
  • 25
  • I came to the screw part... :) What's next? – Jacob Mar 11 '13 at 09:37
  • 2
    `bb.append([array.buffer])` should be `bb.append(array.buffer)`. The append method takes the ArrayBuffer object directly. – quietmint Jun 02 '14 at 17:25
  • In an attempt to save others from a useless ghost-hunt, I took the liberty of fixing the first paragraph of your answer. Within 13 day's after you posted this answer, 'Li Yin' (on the bug-report you linked to), correctly stated that: "Both ArrayBuffer and ArrayBufferView should be supported for Constructor Parameters. So we need to remove the deprecated warning for ArrayBuffer" and submitted a patch to fix the incorrect deprecated warning. – GitaarLAB Mar 24 '15 at 00:27
  • Thank you so much for this... and the specs for what version of each browser/SO was of so much help to me. Really, thank you! – Edson Horacio Junior May 08 '18 at 22:14
1

Got it working with your code. I only had to change some little detail:

if(e.name == 'TypeError' && window.BlobBuilder){
        var bb = new BlobBuilder();
        bb.append(data);
        out = bb.getBlob(datatype);
        console.debug("case 2");
    }

bb.append(data); // data must be with no brackets

My function(constructor) that works now for all browsers:

var NewBlob = function(data, datatype)
{
    var out;

    try {
        out = new Blob([data], {type: datatype});
        console.debug("case 1");
    }
    catch (e) {
        window.BlobBuilder = window.BlobBuilder ||
                window.WebKitBlobBuilder ||
                window.MozBlobBuilder ||
                window.MSBlobBuilder;

        if (e.name == 'TypeError' && window.BlobBuilder) {
            var bb = new BlobBuilder();
            bb.append(data);
            out = bb.getBlob(datatype);
            console.debug("case 2");
        }
        else if (e.name == "InvalidStateError") {
            // InvalidStateError (tested on FF13 WinXP)
            out = new Blob([data], {type: datatype});
            console.debug("case 3");
        }
        else {
            // We're screwed, blob constructor unsupported entirely   
            console.debug("Errore");
        }
    }
    return out;
}
Community
  • 1
  • 1
Jacob
  • 3,580
  • 22
  • 82
  • 146
  • I'm guessing you got marked down for not crediting the other answer as the final solution. Trifling over "data" or "[array.buffer]" when your question used both of them isn't a good reason. – Drew Oct 02 '15 at 14:08
  • 2
    the code for "InvalidStateError" -- `new Blob([data], {type: datatype})` seems the same as the original code your catching! – Ryan Taylor Dec 16 '16 at 15:20