4

I am trying to create a google-chrome-extension that will download an mp3 file. I am trying to use HTML5 blobs and an iframe to trigger a download, but it doesn't seem to be working. Here is my code:

var finalURL = "server1.example.com/u25561664/audio/120774.mp3";

var xhr = new XMLHttpRequest();
    xhr.open("GET", finalURL, true);
    xhr.setRequestHeader('Content-Type', 'application/octet-stream');
    xhr.onreadystatechange = function() 
    {
        if(xhr.readyState == 4 && xhr.status == 200) 
        {   
            var bb = new (window.BlobBuilder || window.WebKitBlobBuilder)();
            bb.append(xhr.responseText);
            var blob = bb.getBlob("application/octet-stream");

            var saveas = document.createElement("iframe");
            saveas.style.display = "none";

            saveas.src = window.webkitURL.createObjectURL(blob); 

            document.body.appendChild(saveas);

            delete xhr;
            delete blob;
            delete bb;
        }
    }
 xhr.send();

When looked in the console, the blob is created correctly, the settings look right:

size: 15312172 type: "application/octet-stream"

However, when I try the link created by the createObjectURL(),

blob:chrome-extension://dkhkkcnjlmfnnmaobedahgcljonancbe/b6c2e829-c811-4239-bd06-8506a67cab04

I get a blank document and a warning saying

Resource interpreted as Document but transferred with MIME type application/octet-stream.

How can get my code to download the file correctly?

Franz Payer
  • 4,069
  • 15
  • 53
  • 77
  • I'm facing a similar situation. I'm using chrome. For me, xhr.status returns 0. Does that mean XMLHttpRequest don't support cross domain scripting? Are there any alternatives? – Sangeeth Saravanaraj Nov 25 '11 at 02:32
  • XMLHttpRequests must follow cross-domain policy. If you want to call a page from another domain, you will need to add the domain in the manifest file for the extension. – Franz Payer Nov 30 '11 at 05:24

2 Answers2

5

The below code worked for me in Google chrome 14.0.835.163:

var finalURL = "http://localhost/Music/123a4.mp3";
var xhr = new XMLHttpRequest();
xhr.overrideMimeType("application/octet-stream");
//xhr.setRequestHeader('Access-Control-Allow-Origin', '*');
xhr.open("GET", finalURL, true);
xhr.responseType = "arraybuffer";
xhr.onload = function() {
      var bb = new (window.BlobBuilder || window.WebKitBlobBuilder)();
      var res = xhr.response;
      if (res){
          var byteArray = new Uint8Array(res);
      }
      bb.append(byteArray.buffer);
      var blob = bb.getBlob("application/octet-stream");
      var iframe = document.createElement("iframe");
      iframe.style.display = "none";
      iframe.src = window.webkitURL.createObjectURL(blob);
      document.body.appendChild(iframe);
};
xhr.send(null);
Benjamin Gruenbaum
  • 270,886
  • 87
  • 504
  • 504
cakiran
  • 66
  • 1
  • 2
  • @Xan any browser with Blobs has XHR2 so doing `onreadystatechange` is redundant at best (you can just `onload`), using `delete` in a GC'd environment is just plain silly and will do nothing in this case (in particular, you can't `delete` what you defined with `var` it's a no-op). I just changed those two things - this answer can be improved a lot further but I didn't want to change its meaning - just the smaller syntax issues. – Benjamin Gruenbaum Feb 04 '15 at 12:38
0

I'm not sure, but i think this is your server's trouble. I've just tried your piece of code to download some sample blob of mp3-file and everything went ok. So maybe:

  1. this file doesn't exist on your server
  2. you server outputs wrong mime type for mp3 files
Dmitrii Sorin
  • 3,855
  • 4
  • 31
  • 40
  • I checked and the file exists on the server, and I am pretty sure that the MIME type is correct. How can I check the mime type that the server is outputting? – Franz Payer May 29 '11 at 15:05
  • The simplest way is to fetch "Content-type" response header: xhr.getResponseHeader('Content-type'); – Dmitrii Sorin May 29 '11 at 20:47
  • I am getting back "audio/mpeg". Can you not use octet-stream for that? Switching getBlob to use "audio/mpeg" gives the same problem. – Franz Payer May 30 '11 at 21:06