通过 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)
}
}
这样做允许我们实际上控制内容长度,并且由于我们可以确定传输的字节数何时等于文件大小,因此我们可以完成该过程.
我们正在利用 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)
}
}
这样做允许我们实际上控制内容长度,并且由于我们可以确定传输的字节数何时等于文件大小,因此我们可以完成该过程.