Question

NOTE: Could somebody give me an example SAS string (with the block info appended in the right area) that needs to be sent to the Azure blob storage? I think that's the issue that I'm having. I need to figure out the order of the uri, key, etc. in the string that is sent to Azure with each block.

What I'm trying to accomplish is to grab a SAS key from a service, modify the string key so that azure knows that I'm sending in blocks, and then send the individual blocks of the file with the sas key from the web client. I'm chunking each file into 2MB blocks and sending those 2MB blocks with a JavaScript library at a time. So each "file" in the code below is just a 2MB chunk of a file.

THE PROBLEM: I can successfully grab the SAS key from the service, modify the key so that it has the block chunk info in it, send in the FIRST chunk, and then receive a response back from the blob storage server. When I send in the second chunk, however, the request for a stream to the blob storage hangs and then eventually times out. The time-out seems to happen specifically on the second request for a stream to the blob storage. This bit of code right here:

SERVER WEB CLIENT CODE:

    using (Stream requestStream = request.GetRequestStream())
    {
        inputStream.CopyTo(requestStream, file.ContentLength);
    }

What could be causing the second chunk to time out? Could it be that the window for the key closes too soon? Below is my code and some screenshots:

    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);
        }

    }

JAVASCRIPT CODE SENDING THE CHUNKS TO THE WEB SERVER CLIENT:

        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);
    });

enter image description here

enter image description here

Was it helpful?

Solution

Issue resolved. It turns out the format of the SAS URI was incorrect. Here is how a Sas URI (for a container, in my case) should look:

http://container_uri/filename?key
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top