index.js 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. /**
  2. * Create a blob builder even when vendor prefixes exist
  3. */
  4. var BlobBuilder = typeof BlobBuilder !== 'undefined' ? BlobBuilder :
  5. typeof WebKitBlobBuilder !== 'undefined' ? WebKitBlobBuilder :
  6. typeof MSBlobBuilder !== 'undefined' ? MSBlobBuilder :
  7. typeof MozBlobBuilder !== 'undefined' ? MozBlobBuilder :
  8. false;
  9. /**
  10. * Check if Blob constructor is supported
  11. */
  12. var blobSupported = (function() {
  13. try {
  14. var a = new Blob(['hi']);
  15. return a.size === 2;
  16. } catch(e) {
  17. return false;
  18. }
  19. })();
  20. /**
  21. * Check if Blob constructor supports ArrayBufferViews
  22. * Fails in Safari 6, so we need to map to ArrayBuffers there.
  23. */
  24. var blobSupportsArrayBufferView = blobSupported && (function() {
  25. try {
  26. var b = new Blob([new Uint8Array([1,2])]);
  27. return b.size === 2;
  28. } catch(e) {
  29. return false;
  30. }
  31. })();
  32. /**
  33. * Check if BlobBuilder is supported
  34. */
  35. var blobBuilderSupported = BlobBuilder
  36. && BlobBuilder.prototype.append
  37. && BlobBuilder.prototype.getBlob;
  38. /**
  39. * Helper function that maps ArrayBufferViews to ArrayBuffers
  40. * Used by BlobBuilder constructor and old browsers that didn't
  41. * support it in the Blob constructor.
  42. */
  43. function mapArrayBufferViews(ary) {
  44. return ary.map(function(chunk) {
  45. if (chunk.buffer instanceof ArrayBuffer) {
  46. var buf = chunk.buffer;
  47. // if this is a subarray, make a copy so we only
  48. // include the subarray region from the underlying buffer
  49. if (chunk.byteLength !== buf.byteLength) {
  50. var copy = new Uint8Array(chunk.byteLength);
  51. copy.set(new Uint8Array(buf, chunk.byteOffset, chunk.byteLength));
  52. buf = copy.buffer;
  53. }
  54. return buf;
  55. }
  56. return chunk;
  57. });
  58. }
  59. function BlobBuilderConstructor(ary, options) {
  60. options = options || {};
  61. var bb = new BlobBuilder();
  62. mapArrayBufferViews(ary).forEach(function(part) {
  63. bb.append(part);
  64. });
  65. return (options.type) ? bb.getBlob(options.type) : bb.getBlob();
  66. };
  67. function BlobConstructor(ary, options) {
  68. return new Blob(mapArrayBufferViews(ary), options || {});
  69. };
  70. if (typeof Blob !== 'undefined') {
  71. BlobBuilderConstructor.prototype = Blob.prototype;
  72. BlobConstructor.prototype = Blob.prototype;
  73. }
  74. module.exports = (function() {
  75. if (blobSupported) {
  76. return blobSupportsArrayBufferView ? Blob : BlobConstructor;
  77. } else if (blobBuilderSupported) {
  78. return BlobBuilderConstructor;
  79. } else {
  80. return undefined;
  81. }
  82. })();