简体   繁体   中英

Javascript: converting binary data in Uint8Array to string corrupting file

I'm trying to upload a video file in chunks to a server via a standard jQuery $.ajax call. The process is simple:

  1. Use the slice() method on the file object to read a chunk
  2. Use FileReader.readAsArrayBuffer to read the resulting blob
  3. Create a Uint8Array of that result in the FileReader.onload callback
  4. Use String.fromCharCode.apply(null, intArrayName) to convert it into a binary string
  5. Upload that binary string as a chunk in the AJAX call's data property

When I finish uploading all the chunks, the server's API complains that the file upload is incomplete. To test this method, I converted the concatenated binary strings into a Blob and had Chrome save it to my downloads folder, only to find out my media player said the file was unplayable.

I've read posts on this site and other articles suggesting that directly converting binary data represented by integers to strings results in a loss of data, and that the suggestion is convert it to a base64-encoded string, since Javascript doesn't have a StreamContent object like C# does.

The problem is that even if I set Content-Transfer-Encoding to base64 I don't think the API (which wasn't written by us) picks up on it and can tell that a base64 decoding is needed.

My question is: is this the only sure-fire way of sending video data over an AJAX call safely? If not, how else can I send it in the data field of my AJAX request? There are probably thousands of uploaders like this on the Internet but nowhere can I find solid documentation on how to do this. If it turns out that the server needs to expect base64 encoding, we might have to write a middle-man API to do this decoding for us.

Thanks to Patrick Evans , it turns out all I needed to do was upload the blob itself:

function upload(file) {
  var offset = 0; // what's been sent already
  var fileSize = file.size;
  var chunkSize = 64 * 1024; // bytes

  while (offset < fileSize) {
    var blob = file.slice(offset, chunkSize + offset);

    var urlToUse = ((offset + blob.size) >= fileSize) ? videoFinishBaseUrl : videoContinueBaseUrl;

    $.ajax({
      url: urlToUse,
      method: 'POST',
      data: blob,
      headers: requestHeaders,
      contentType: false,
      processData: false,
      cache: false,
      async: false,
      success: function(data) {
        jQuery('#uploadmsg').text('Finished offset ' + offset);
        offset += blob.size;
      },
      error: function(err) {
        jQuery('#uploadmsg').text(err);
      }
    });

  }
};

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM