ArbitB
ArbitB

Reputation: 113

Uploading files to azure storage from client

I have read a lot of already existing questions on uploading a file to azure storage directly from client-side/browser. The one I am implementing is from this blog by gaurav mantri. In this blog he splits the SAS url into path and query and then append file name to the path and then stiched the query again to it. I have SAS url which doesn't have any query. I just have url like this

This SAS url has the file name also appended in it. In the blog he appends blockId and blockList etc. Do it really need to do that? If not how should I make PUT request? Just using my SAS url would work?

Update: I have included query parameter (SAS token) as "URL?SAS-TOKEN". Now I am getting error like this

Error

  dll.vendor.js:44368 PUT https://triggerbackendnormal.blob.core.windows.net/backend-media/a07d312c-6…Vhgoxw/NmD2AeSo4qVhBntrI04xJo1tsqfKJA/7bmQ%3D&comp=block&blockid=undefined 400 (Value for one of the query parameters specified in the request URI is invalid.)CORS

CORS Rules Setup in portal: image of CORS Rules Setup in portal

JS code:

 handleFileSelect(e) {
        var that = this
        maxBlockSize = 256 * 1024;
        currentFilePointer = 0;
        totalBytesRemaining = 0;
        files = e.target.files;
        selectedFile = files[0];
        console.log(selectedFile.name)
        console.log(selectedFile.size)
        console.log(selectedFile.type)
        var fileSize = selectedFile.size;
        if (fileSize < maxBlockSize) {
            maxBlockSize = fileSize;
            console.log("max block size = " + maxBlockSize);
        }
        totalBytesRemaining = fileSize;
        if (fileSize % maxBlockSize == 0) {
            numberOfBlocks = fileSize / maxBlockSize;
        } else {
            numberOfBlocks = parseInt(fileSize / maxBlockSize, 10) + 1;
        }
        console.log("total blocks = " + numberOfBlocks);
        // $("#fileName").text(selectedFile.name);
        // $("#fileSize").text(selectedFile.size);
        // $("#fileType").text(selectedFile.type);

        var baseUrl = 'https://example.blob.core.windows.net/backend-m/a07d312c-6e7a-4281-9e4f-050f5afc4609.mp4?sr=b&se=2017-05-04T15%3A07%3A30Z&sp=w&sv=2016-05-31&sig=SVhgoxw/NmD2AeSo4qVhBntrI04xJo1qfKJA/7bmQ%3D'
        submitUri = baseUrl
        console.log(submitUri);

        this.uploadFileInBlocks();

    }
        //var fileContent = selectedFile.slice(currentFilePointer, currentFilePointer + maxBlockSize);
        //currentFilePointer =+ maxBlockSize;





    uploadFileInBlocks() {
        if (totalBytesRemaining > 0) {
            console.log("current file pointer = " + currentFilePointer + " bytes read = " + maxBlockSize);
            var fileContent = selectedFile.slice(currentFilePointer, currentFilePointer + maxBlockSize);
            var blockId = blockIdPrefix + this.pad(blockIds.length, 6);
            console.log("block id = " + blockId);
            blockIds.push(btoa(blockId));
            reader.readAsArrayBuffer(fileContent);
            currentFilePointer += maxBlockSize;
            totalBytesRemaining -= maxBlockSize;
            if (totalBytesRemaining < maxBlockSize) {
                maxBlockSize = totalBytesRemaining;
            }
        } else {
            this.commitBlockList();
        }
    }

    commitBlockList() {
        var uri = submitUri + '&comp=blocklist';
        console.log(uri);
        var requestBody = '<?xml version="1.0" encoding="utf-8"?><BlockList>';
        for (var i = 0; i < blockIds.length; i++) {
            requestBody += '<Latest>' + blockIds[i] + '</Latest>';
        }
        requestBody += '</BlockList>';
        console.log(requestBody);
        $.ajax({
            url: uri,
            type: "PUT",
            data: requestBody,
            beforeSend: function (xhr) {
                //xhr.setRequestHeader('x-ms-blob-content-type', selectedFile.type);
                //xhr.setRequestHeader('Content-Length', requestBody.length);
            },
            success: function (data, status) {
                console.log(data);
                console.log(status);
            },
            error: function (xhr, desc, err) {
                console.log(desc);
                console.log(err);
            }
        });

    }
    pad(number, length) {
        var str = '' + number;
        while (str.length < length) {
            str = '0' + str;
        }
        return str;
    }

    render(){

        reader.onloadend = function (evt) {
            if (evt.target.readyState == FileReader.DONE) { // DONE == 2
                var uri = submitUri + '&comp=block&blockid=' + blockIds[blockIds.length - 1];
                var requestData = new Uint8Array(evt.target.result);
                $.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) {
                        console.log(data);
                        console.log(status);
                        bytesUploaded += requestData.length;
                        var percentComplete = ((parseFloat(bytesUploaded) / parseFloat(selectedFile.size)) * 100).toFixed(2);
                        console.log(percentComplete)
                        this.uploadFileInBlocks();
                    },
                    error: function(xhr, desc, err) {
                        console.log(desc);
                        console.log(err);
                    }
                });
            }
        };

        return (
            <label htmlFor='myInput'>
                <input id="myInput" type="file" ref={(ref) => this.upload = ref} style={{visibility: 'hidden'}} onChange={this.handleFileSelect.bind(this)}/>
                <FloatingActionButton
                    className="floatingButton"
                    backgroundColor='#fb802a'
                    onClick={(e) => this.upload.click() }>
                    <ContentAdd />
                </FloatingActionButton>
            </label>
        )
    }

Upvotes: 1

Views: 1128

Answers (2)

ArbitB
ArbitB

Reputation: 113

For ReactJS, this is how it should be done

handleFileSelect(e) {
        var that = this
        maxBlockSize = 256 * 1024;
        currentFilePointer = 0;
        totalBytesRemaining = 0;
        files = e.target.files;
        selectedFile = files[0];
        console.log(selectedFile.name)
        console.log(selectedFile.size)
        console.log(selectedFile.type)
        var fileSize = selectedFile.size;
        if (fileSize < maxBlockSize) {
            maxBlockSize = fileSize;
            console.log("max block size = " + maxBlockSize);
        }
        totalBytesRemaining = fileSize;
        if (fileSize % maxBlockSize == 0) {
            numberOfBlocks = fileSize / maxBlockSize;
        } else {
            numberOfBlocks = parseInt(fileSize / maxBlockSize, 10) + 1;
        }
        console.log("total blocks = " + numberOfBlocks);
        // $("#fileName").text(selectedFile.name);
        // $("#fileSize").text(selectedFile.size);
        // $("#fileType").text(selectedFile.type);
    var baseUrl = 'https://example.blob.core.windows.net/backend-media/e7581d7b-a59d-47eb-b8aa-6b6799179b36.mp4?sv=2016-05-31&sr=b&se=2017-05-09T18%3A26%3A07Z&sp=w&sig=TlS/a9RgVT/j7BHztjFZSF2L2skno3Sko%3D'
    submitUri = baseUrl
    console.log(submitUri);

    this.uploadFileInBlocks();

}


loadEnd(evt){
    var that = this;
    if (evt.target.readyState == FileReader.DONE) { // DONE == 2
        var uri = submitUri + '&comp=block&blockid=' + blockIds[blockIds.length - 1];
        var requestData = new Uint8Array(evt.target.result);
        $.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) {
                console.log(data);
                console.log("hi" + status);
                bytesUploaded += requestData.length;
                var percentComplete = ((parseFloat(bytesUploaded) / parseFloat(selectedFile.size)) * 100).toFixed(2);
                console.log(percentComplete)
                that.uploadFileInBlocks();
            },
            error: function(xhr, desc, err) {
                console.log(desc);
                console.log(err);
            }
        });
    }
}

uploadFileInBlocks() {
    if (totalBytesRemaining > 0) {
        console.log("current file pointer = " + currentFilePointer + " bytes read = " + maxBlockSize);
        var fileContent = selectedFile.slice(currentFilePointer, currentFilePointer + maxBlockSize);
        var blockId = blockIdPrefix + this.pad(blockIds.length, 6);
        console.log("block id = " + blockId);
        blockIds.push(btoa(blockId));
        reader.readAsArrayBuffer(fileContent);
        reader.onloadend = this.loadEnd.bind(this);
        currentFilePointer += maxBlockSize;
        totalBytesRemaining -= maxBlockSize;
        if (totalBytesRemaining < maxBlockSize) {
            maxBlockSize = totalBytesRemaining;
        }
    } else {
        this.commitBlockList();
    }
}

commitBlockList() {
    var uri = submitUri + '&comp=blocklist';
    console.log(uri);
    var requestBody = '<?xml version="1.0" encoding="utf-8"?><BlockList>';
    for (var i = 0; i < blockIds.length; i++) {
        requestBody += '<Latest>' + blockIds[i] + '</Latest>';
    }
    requestBody += '</BlockList>';
    console.log(requestBody);
    $.ajax({
        url: uri,
        type: "PUT",
        data: requestBody,
        beforeSend: function (xhr) {
            //xhr.setRequestHeader('x-ms-blob-content-type', selectedFile.type);
            //xhr.setRequestHeader('Content-Length', requestBody.length);
        },
        success: function (data, status) {
            console.log(data);
            console.log("hi" + status);
        },
        error: function (xhr, desc, err) {
            console.log(desc);
            console.log(err);
        }
    });

}
pad(number, length) {
    var str = '' + number;
    while (str.length < length) {
        str = '0' + str;
    }
    return str;
}

render(){

    reader.onloadend = function (evt) {
        if (evt.target.readyState == FileReader.DONE) { // DONE == 2
            var uri = submitUri + '&comp=block&blockid=' + blockIds[blockIds.length - 1];
            var requestData = new Uint8Array(evt.target.result);
            $.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) {
                    console.log(data);
                    console.log(status);
                    bytesUploaded += requestData.length;
                    var percentComplete = ((parseFloat(bytesUploaded) / parseFloat(selectedFile.size)) * 100).toFixed(2);
                    console.log(percentComplete)
                    this.uploadFileInBlocks();
                },
                error: function(xhr, desc, err) {
                    console.log(desc);
                    console.log(err);
                }
            });
        }
    };

    return (

Upvotes: 0

Gaurav Mantri
Gaurav Mantri

Reputation: 136379

I have SAS url which doesn't have any query. I just have url like this 'https://exapmplename.blob.core.windows.net/backend/a074281-9e4f-050f5afc4609.mp4'

This is not a SAS URL. It is simply a URL for the blob. A SAS URL has Shared Access Signature parameters like sig, se, sv etc. appended to the URL as querystring parameters. I would suggest you create a SAS URL and use that. In order to upload a blob, the SAS URL must have Write permission.

In the blog he appends blockId and blockList etc. Do it really need to do that?

It depends! If you're uploading blob without splitting the file in blocks using Put Blob REST API, then you need not do that. However if you need to split the file into blocks and use Put Block and Put Block List REST API, then you have to do that.

If not how should I make PUT request?

If your file is small and have good Internet speed, then you really need not split the file in smaller chunks and upload a file in one go using Put Blob REST API.

Upvotes: 1

Related Questions