1

I'm building an ajax file uploader, which is possible thanks to the new FormData interface. It works if I use the original file, but if I convert the file to a binary string and then to a blob, the resulting file is corrupted. What am I doing wrong?

<!DOCTYPE html>
<html>
  <body>
    <form method=post enctype=multipart/form-data id=form>
      <input id=file type=file name=file>
      <button id=1>1</button>
      <button id=2>2</button>
    </form>
    <script>
      var d = document;

      function $(id) { return d.getElementById(id); };

      function xhr(fd) {
        var x = new XMLHttpRequest();
        x.open('post', '/', true);
        x.send(fd);
      };

      $(1).addEventListener('click', function(e) {
          e.preventDefault();
          var file = $('file').files[0];
          var fd = new FormData();
          fd.append('file', file);
          xhr(fd);
        }, false
      );

      $(2).addEventListener('click', function(e) {
          e.preventDefault();
          var file = $('file').files[0];
          var fr = new FileReader();
          fr.onload = function(e) {
            var bb = new (window.BlobBuilder ||
              window.MozBlobBuilder || window.WebKitBlobBuilder)()
            bb.append(e.target.result);
            var b = bb.getBlob(file.type);
            var fd = new FormData();
            fd.append('file', b);
            xhr(fd);
          };
          fr.readAsBinaryString(file);
        }, false
      );
    </script>
  </body>
</html>

Blob BlobBuilder FileReader FormData

edited to include links

aeosynth
  • 20,750
  • 2
  • 21
  • 18

2 Answers2

1

I got it working in Firefox / Chrome by converting the string into a Uint8Array:

var result = e.target.result;
var l = result.length
var ui8a = new Uint8Array(l)
for (var i = 0; i < l; i++)
  ui8a[i] = result.charCodeAt(i);
bb.append(ui8a.buffer)
aeosynth
  • 20,750
  • 2
  • 21
  • 18
0

I'm not familiar with most of these objects, but I noticed that you reference file.type in the fr.onload function of your second event listener. Is file in scope at that point? Shouldn't you be using e instead?

Matt McHugh
  • 3,995
  • 1
  • 15
  • 8
  • I added some links. Yes, `file` is still in the scope; inner functions have access to the outer function's scope. http://stackoverflow.com/questions/500431/javascript-variable-scope https://developer.mozilla.org/en/JavaScript/Reference/Functions_and_function_scope#Nested_functions_and_closures – aeosynth Aug 27 '11 at 02:38
  • Interesting, I didn't know that. – Matt McHugh Aug 27 '11 at 10:28