使用PUT BLOCK将视频上传到Azure Blob存储

时间:2014-09-23 20:54:20

标签: ajax cordova azure html5-video azure-storage-blobs

我遇到了Windows Azure Blob存储的两个问题。

我正在开发一个记录视频的PhoneGap / Cordova移动应用程序,然后使用javascript将视频上传到Azure Blob存储。我正在使用Gaurav Mantri博客文章中的一个很好的javascript配方:http://gauravmantri.com/2013/02/16/uploading-large-files-in-windows-azure-blob-storage-using-shared-access-signature-html-and-javascript/

问题1:上传过程非常缓慢。我使用PUT BLOCK Api,其中视频文件一次上传一个块(大约256 KB /文件),最终整个文件使用PUT BLOCK LIST提交。一个小的mp4视频,例如14秒/ 10 MB,上传需要5-10分钟!会发生什么事情是很多块会被快速上传,然后突然间进程将暂停几分钟而没有任何反应(通常是40-60%的块被上传),然后它会在暂停之前快速上传另一批块再次。

以下是我用来上传的javascript片段:

  reader.onloadend = function (evt) {
  if (evt.target.readyState == FileReader.DONE) 
  { 
  var requestData = new Uint8Array(evt.target.result);
  var blockId = blockIdPrefix + pad(blockIds.length, 6);
  blockIds.push(btoa(blockId));
  var uri = submitUri + '&comp=block&blockid=' + blockIds[blockIds.length-1];
  $.support.cors = true;
  $.ajax({
      url: uri,
      type: "PUT",
      data: requestData,
      processData: false,
      beforeSend: function(xhr) {
          xhr.setRequestHeader('x-ms-blob-type', 'BlockBlob');
          //xhr.setRequestHeader('Content-Length', requestData.length);
      },
      success: function (data, status) {
        bytesUploaded += requestData.length;
        var percentComplete = ((parseFloat(bytesUploaded) / parseFloat(selectedFile.size)) * 100).toFixed(2);
        console.log(percentComplete + " %");
            uploadFileInBlocks();
              },
            error: function(xhr, desc, err) {
                console.log(desc);
                console.log(err);
            }
          });
      }
  };


function uploadFileInBlocks() {
    if (totalBytesRemaining > 0) {
        var fileContent = selectedFile.slice(currentFilePointer, currentFilePointer + maxBlockSize);
        reader.readAsArrayBuffer(fileContent);
        currentFilePointer += maxBlockSize;
        totalBytesRemaining -= maxBlockSize;
        if (totalBytesRemaining < maxBlockSize) {
            maxBlockSize = totalBytesRemaining;
        }
    } else {
        commitBlockList();
    }
}

存储帐户配置为使用CORS,并且已从Azure管理工作室生成SAS uri(SAS uri不像其他许多示例那样动态生成)。除了地理冗余帐户之外,我还尝试过切换到本地冗余存储帐户,但这并不能使上传速度更快。不幸的是,由于代码在我的Android手机上运行,​​我无法跟踪Fiddler或tcpdump的流量。

从Blob存储文档:

&#34;可以用两种方式之一创建块blob。可以通过调用Put Blob操作上载小于或等于64 MB大小的块blob。必须将大于64 MB的块blob作为一组块上载,每个块的大小必须小于或等于4 MB。通过调用Put Block List,可以按指定的顺序将一组成功上载的块组合成单个连续的blob。块blob当前支持的最大大小为200 GB。&#34;

我正在使用SAS URI中指定的存储版本2014-02-14:appname.blob.core.windows.net/asset-10146439-dbe1-4af9-85df-a94cf91ef2ec?sr=c&sv= 2014年2月14日&安培; ST = 2014-08-13T18%3A01%3A52Z&安培; SE = 2014-10-18T19%3A01%3A52Z&安培; SP =&RWL放大器; SIG = mysignature

我认为上传速度要快得多的原因是因为当我使用PUT BLOB api上传例如10 MB的文件时 - 它发生得非常快(大约20-30秒)。但是,正如上面的文档所述,PUT BLOB只能用于小于64 MB的文件,这导致了我的第二个问题:

问题2:当我使用PUT BLOB api时,会在视频文件的开头插入Content-Disposition标头,使播放失败(视频应该从html5视频元素播放)。如何在使用PUT BLOB时避免自动插入Content-Disposition标头?我在上传时尝试将x-ms-blob-content-disposition显式设置为空字符串,但不幸的是它似乎没有效果(标题仍然存在)。

与PUT BLOB一起使用的代码是:

var ft = new FileTransfer(),
options = new FileUploadOptions();

options.httpMethod = "PUT";
options.chunkedMode = false;
options.headers = {
        'x-ms-blob-type': 'BlockBlob'
        ,'Content-Type': 'video/mp4'
};

ft.upload(mediaFile.toURL(), submitUri,
    function (e) {
        console.log("upload success!");
    },
    function (e) {
        alert("Upload failed");
    }, options);

我还尝试了第三种方法,即使用XMLHttpRequest上传文件,这会产生一个没有Content-Disposition标头的文件,但是视频文件以某种方式被破坏 - 它无法播放,不能播放甚至在将它下载到桌面时(我已经在十六进制编辑器中打开了视频文件,文件的起始字节看起来与来自有效mp4文件的字节完全一样......也许是精通mp4格式的人可以找出问题所在,这里有一个这样一个破损的视频文件的例子:https://onedrive.live.com/redir?resid=B3105327829B3E0C!23617&authkey=!AHoS6cZJmDlIN-E&ithint=file%2cmp4

var ajaxRequest = new XMLHttpRequest();
var rawData = null;

 try {
reader = new FileReader();

reader.onload = function (evt) {
    rawData = reader.result;
    ajaxRequest.open('PUT', submitUri, true);
    ajaxRequest.setRequestHeader('Content-Type', 'video/mp4');
    ajaxRequest.setRequestHeader('x-ms-blob-type', 'BlockBlob');
    ajaxRequest.send(rawData);
    console.log("done uploading!")    
}

reader.readAsBinaryString(selectedFile)

非常感谢任何指示,谢谢!

0 个答案:

没有答案