通过 VMware API 上传媒体导致传输的大小大于文件大小

Upload of Media via VMware API results in larger transferred size than file size

我们正在利用 V Cloud API 与虚拟机交互(创建机器、执行操作、切换媒体等)。一个请求的功能是能够将媒体(特别是 ISO)上传到特定的目录。 API guide (pg 67) 非常简单,我们的 multi-part 对上传开始时提供的 URL 的请求顺利进行。

注意:我们必须在开始上传之前声明文件大小

在上传过程中唯一似乎不对劲的是 "transferred size" 在过程结束时最终比 "file size" 大。这有点奇怪,因为我们的 content-range 从未超过预期的文件大小(我们假设元数据在我们没有发言权的情况下被包含在内)。一旦此传输大小超过文件大小,文件上传状态将更改为 "Error" 但仍然 returns 和 200 OK

    {
  "name": "J Small 4",
  "description": "",
  "files": [{
    "name": "file",
    "totalSize": 50696192,
    "status": "Error",
    "link": "https://cloud01.cs2cloud.com/transfer/27b8f93c-8319-419e-9e8c-15622097670b/file",
    "transferredSize": 54293177
  }],
  "id": "urn:vcloud:media:1cec68ef-f22e-4ec7-ae5d-dfbc4f7137d9",
  "catalogId": "urn:vcloud:catalogitem:19dbfdd8-ea70-4355-abc7-96e34dccb869"
}

不知道从哪里开始调试这个,因为所有 API 调用都返回 200 OK.ISO file 似乎没问题,我们的 content-range headers 永远不会超出既定的文件大小,并且 meta-data 似乎在编辑或测量方面超出了我们的控制范围。

希望有人曾经遇到过这个问题,并且可以提供一些见解来寻求解决方案

事实证明,问题根本不在于 vmware,而在于我们如何对媒体文件进行分块。我们最初使用 FileReader() 将文件分块并将其发送到 VMware API。

理论上,我们选择的是块大小,然后可以生成和设置内容范围,但实际上我们选择的是内容范围,但内容长度与块大小不同。我们仍然不完全确定它发生的原因(可能添加了额外的元数据)但我们找到了解决方案。

修复:我们完全取消了 FileReader(),只是将文件切片直接放入 blob(您可以在下面看到)

$scope.parseMediaFile = function(url, file, catalogId) {
         $scope.uploadingMediaFile = true;

         var fileSize = file.size;
         var chunkSize = 1024 * 1024 * 5; // bytes
         var offset = 0;
         var self = this; // we need a reference to the current object
         var chunkReaderBlock = null;
         var chunkNum = 0;

         if (fileSize < chunkSize) {
            chunkSize = fileSize;
         }

         chunkReaderBlock = function(_offset, length, _file) {
            var blob = _file.slice(_offset, length + _offset);
            var beginRange = _offset;
            var endRange = _offset + length;

            if(endRange > _file.size) {
              endRange = _file.size
            }

            var contentRange = beginRange + "-" + endRange;

            vdcServices.uploadMediaFile(url, blob, fileSize, contentRange).then(
              function(resp) {
                vdcServices.getUploadStatus($scope.company, catalogId).then(function(resp) {
                  var uploaded = resp.data.files[0].transferredSize;
                  $scope.mediaPercentLoaded = $scope.trunc((uploaded / fileSize) * 100);

                  if (endRange == _file.size) {
                    $scope.closeModal();
                    return;
                  }

                  chunkReaderBlock(_offset+length, chunkSize, file);
                }, function(err) {
                  $scope.errorMsg = err;
                  chunkReaderBlock(_offset-length, chunkSize, file);
                })
              },
              function(err) {
                $scope.errorMsg = err;
              }
            )
         }

         // Starts the read with the first block
         if (offset < fileSize) {
            chunkReaderBlock(offset, chunkSize, file)
         }

      }

这样做允许我们实际上控制内容长度,并且由于我们可以确定传输的字节数何时等于文件大小,因此我们可以完成该过程.