注意:有人可以给我一个需要发送到 Azure blob 存储的示例 SAS 字符串(在右侧区域附加块信息)吗?我认为这就是我遇到的问题。我需要弄清楚每个块发送到 Azure 的字符串中 uri、key 等的顺序。
我想要完成的是从服务中获取一个 SAS 密钥,修改字符串密钥,以便 azure 知道我正在发送块,然后使用来自 Web 客户端的 sas 密钥发送文件的各个块. 我将每个文件分块为 2MB 块,并一次使用 JavaScript 库发送这些 2MB 块。所以下面代码中的每个“文件”只是一个 2MB 的文件块。
问题:我可以成功地从服务中获取 SAS 密钥,修改密钥使其包含块块信息,发送第一个块,然后从 blob 存储服务器接收响应。但是,当我发送第二个块时,对 blob 存储的流的请求挂起,然后最终超时。超时似乎专门发生在第二次请求到 blob 存储的流时。这段代码就在这里:
服务器网页客户端代码:
using (Stream requestStream = request.GetRequestStream())
{
inputStream.CopyTo(requestStream, file.ContentLength);
}
什么可能导致第二个块超时?会不会是钥匙的窗口关得太早了?下面是我的代码和一些截图:
private void WriteToBlob(HttpPostedFileBase file, string BlockId, FileProp fp)
{
var inputStream = file.InputStream;
Microsoft.WindowsAzure.StorageCredentialsSharedAccessSignature credentials =
new Microsoft.WindowsAzure.StorageCredentialsSharedAccessSignature(fp.facct);
string queryString = (new Uri(fp.folderName)).Query;
string RequestUri = string.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}/{1}{2}&comp=block&blockid={3}",
fp.folderName, fp.fileName, queryString, Convert.ToBase64String(Encoding.UTF8.GetBytes(BlockId)));
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(RequestUri);
request.Method = "PUT";
request.ContentLength = inputStream.Length;
using (Stream requestStream = request.GetRequestStream())
{
inputStream.CopyTo(requestStream, file.ContentLength);
}
}
将块发送到 WEB 服务器客户端的 JAVASCRIPT 代码:
var running = 0;
var chunksize = (Modernizr.blobconstructor) ? uploadChunkSize : null; //if browser support Blob API
window.xhrPool = [];
$('#fileupload').fileupload({
url: url,
//formData: [{ name: 'param1', value: 1 }, { name: 'param2', value: 2}],
singleFileUploads: true, //each file is using an individual XHR request
//limitMultiFileUploads: 2, //This option is ignored, if singleFileUploads is set to true.
multipart: true,
maxChunkSize: chunksize, //server side is in streaming mode
sequentialUploads: true, //Set this option to true to issue all file upload requests in a sequential order instead of simultaneous requests.
dataType: 'json',
autoUpload: true,
//acceptFileTypes: /(\.|\/)(gif|jpe?g|png)$/i,
progressInterval: 100,
bitrateInterval: 100,
maxFileSize: uploadFileSizeLimit
}).on('fileuploadadd', function (e, data) {
var filename = data.files[0].name;
var filesize = data.files[0].size;
if (filesize == 0) {
var zeroSizeErrMsg = sceneLayoutService.format('This file {filename} is empty please select files again without it. ', { filename: filename });
sceneLayoutService.showErrorDialog(zeroSizeErrMsg);
return;
}
if (window.availableStorageSize != null && window.availableStorageSize != '') {
if (filesize > window.availableStorageSize) {
var overSizeErrMsg = sceneLayoutService.format('File size of {filename} exceeds available storage space in your cloud drive. ', { filename: filename });
sceneLayoutService.showErrorDialog(overSizeErrMsg);
return;
}
} else {
alert('Unable to retrieve the storage usage.');
}
data.jqXHR = data.submit();
window.xhrPool.push(data.jqXHR);
sceneLayoutService.addFileToProgressDialog(data, cancelButton);
}).on('fileuploadprocessalways', function (e, data) {
}).on('fileuploadprogressall', function (e, data) {
}).on('fileuploadsubmit', function (e, data) {
var filesize = data.files[0].size;
if (filesize == 0) {
return false;
}
if (window.availableStorageSize != null && window.availableStorageSize != '') {
if (filesize > window.availableStorageSize) {
return false;
}
}
$('#dlgProgress').parent().show();
running++;
sceneLayoutService.showProgressDialog('Uploading files to ' + currentUser + '\'s Cloud Storage ...', abortAllUploads);
return true;
}).on('fileuploaddone', function (e, data) {
running--;
updateStorageQuota(function () {
var usedStorageSize = (window.usedStorageSize != null) ? bytesToSize(window.usedStorageSize, 2) : 0;
var totalStorageSize = (window.totalStorageSize != null) ? bytesToSize(window.totalStorageSize, 2) : 0;
var usageFooterStr = sceneLayoutService.format("Using {used} of {total} (%)", { used: usedStorageSize, total: totalStorageSize });
$('div.dlgProgressFooter').text(usageFooterStr);
});
var docGridUrl = window.baseUrl + '/CloudStorage/ChangePage?page=1&rand=' + sceneLayoutService.getRandomString(4);
$('#docGridPartial').load(docGridUrl, function () {
grid.init({
pageNumber: 1,
url: window.baseUrl + '/CloudStorage/ChangePage',
sortColumn: '',
sortDirection: ''
});
});
sceneLayoutService.updateFileUploadFinalStatus(data, 'done');
if (!data.result.success) {
debugger;
var errMsg = "";
if (data.result != null) {
if (data.result.message != null) {
errMsg += data.result.message;
}
if (data.result.error != null)
errMsg += data.result.error;
}
sceneLayoutService.showErrorDialog(errMsg);
}
window.removeXHRfromPool(data);
if (running == 0) {
$('#dlgProgress').parent().hide();
$('#progresses').empty();
}
}).on('fileuploadfail', function (e, data) {
running--;
sceneLayoutService.updateFileUploadFinalStatus(data, 'fail');
window.removeXHRfromPool(data);
if (running == 0) {
$('#dlgProgress').parent().hide();
$('#progresses').empty();
}
}).on('fileuploadprogress', function (e, data) {
//XHR upload onProgress event not fired at server-defined intervals/not supported in IE8 and IE9,
//will be supported in IE10 in terms of XMLHttpRequest Level 2 specification, http://caniuse.com/xhr2
sceneLayoutService.updateFileUploadProgress(data);
});