Javascript 上傳文件到Azure存儲

對一些前端工程師來說,使用javascript上傳文件到Azure存儲中多是須要掌握的技能,但願這篇博客能給到幫助。javascript

在開始前咱們須要瞭解如下幾點:html

共享訪問簽名(Shared Access Signature(SAS)前端

Azure 存儲服務的跨域資源共享 (CORS) 支持java

 

共享訪問簽名jquery

共享訪問簽名,是用於提供對Windows Azure Storage中的Container,Blob,Table以及Queue在特定時間範圍內進行有限權限訪問的URL。一般狀況下,咱們訪問Azure存儲都是以帳戶名和密碼的方式來實現的,經過這種方式也給使用者包括增刪改在內的最大的訪問權限,可是在實際狀況中,咱們可能但願用戶只有讀的權限,同時咱們也不但願將帳戶名和密碼泄露出去,共享訪問簽名很好的解決了這類問題。咱們在使用Javascript上傳時就是經過共享訪問簽名的URL來進行的。ajax

 

Azure 存儲服務的跨域資源共享 (CORS) 支持編程

大概在2014年3月份的時候Azure已經支持CORS,通過測試目前中國版和國際版都已經支持,咱們在使用Javascript上傳的時候是將資源以PUT的方式上傳到相似於http://***.blob.core.chinacloudapi.cn這樣域名的地方,這就涉及到CORS的問題,在默認狀況下Azure存儲是禁用CORS的,因此咱們須要使用版本 2013-08-15 或更高版本設置適當的服務屬性,並向服務屬性中添加 CORS 規則,若是咱們沒有啓用CORS規則,咱們可能會獲得403錯誤,使用Fiddler工具會獲得更詳細的錯誤信息:」CORS not enabled or no matching rule found for this request」。windows

 

經過上面的描述,咱們在開始編程前,咱們須要SAS URL,還須要爲咱們的blob配置CORS規則,這些咱們能夠經過Azure SDK來實現,關於這部分我就不介紹了,詳細請閱讀:#SAS:http://www.windowsazure.cn/zh-cn/documentation/articles/storage-dotnet-shared-access-signature-part-2/api

#CORS:http://blogs.msdn.com/b/windowsazurestorage/archive/2014/02/03/windows-azure-storage-introducing-cors.aspx跨域

若是咱們不太瞭解C#,咱們能夠藉助Azure Storage Explorer來進行配置,下面我介紹下簡單的配置:

1)  獲得SAS URL

                       

打開Azure Storage Explorer點擊「Security」,選擇SAS失效的時間,並選擇賦予相應的權限,如上圖高亮標註的部分。

2)  配置CORS規則

 

打開Azure Storage Explorer鼠標停留在」Blob Containers」,這時會出現CORS設置按鈕,點擊新增CORS規則,並如上圖設置,關於具體的設置信息,請閱讀:https://msdn.microsoft.com/zh-cn/library/azure/dn535601.aspx?f=255&MSPPError=-2147217396,圖中的設置是我測試的字段,可做爲參考。

 

下面是具體的代碼

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">

<head>

    <title>File Uploader</title>

 

    <script src="Scripts/jquery-1.10.2.min.js"></script>

 

    <script>

        var maxBlockSize = 256 * 1024;//Each file will   be split in 256 KB.

        var numberOfBlocks = 1;

        var selectedFile = null;

        var currentFilePointer = 0;

        var totalBytesRemaining = 0;

        var blockIds = new Array();

        var blockIdPrefix = "block-";

        var submitUri = null;

        var bytesUploaded = 0;

 

        $(document).ready(function () {

            $("#output").hide();

            $("#file").bind('change',   handleFileSelect);

            if (window.File &&   window.FileReader && window.FileList && window.Blob) {

                // Great success!   All the File APIs are supported.

            } else {

                alert('The File APIs are   not fully supported in this browser.');

            }

        });

 

        //Read the file and find out how   many blocks we would need to split it.

        function handleFileSelect(e) {

            maxBlockSize = 256 *   1024;

            currentFilePointer =   0;

            totalBytesRemaining =   0;

            var files = e.target.files;

            selectedFile =   files[0];

            $("#output").show();

            $("#fileName").text(selectedFile.name);

            $("#fileSize").text(selectedFile.size);

            $("#fileType").text(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);

            var baseUrl = $("#sasUrl").val();

            var indexOfQueryStart = baseUrl.indexOf("?");

            submitUri =   baseUrl.substring(0, indexOfQueryStart) + '/' + selectedFile.name +   baseUrl.substring(indexOfQueryStart);

              console.log(submitUri);

        }

 

        var reader = new FileReader();

 

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

                        $("#fileUploadProgress").text(percentComplete   + "   %");

                          uploadFileInBlocks();

                    },

                    error: function (xhr, desc, err)   {

                          console.log(desc);

                          console.log(err);

                    }

                });

            }

        };

 

        function uploadFileInBlocks() {

            if (totalBytesRemaining > 0) {

                console.log("current file   pointer = " + currentFilePointer + " bytes read = " + maxBlockSize);

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

                var blockId = blockIdPrefix +   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 {

                commitBlockList();

            }

        }

 

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

                }

            });

 

        }

        function pad(number, length) {

            var str = '' + number;

            while (str.length < length) {

                str = '0' + str;

            }

            return str;

        }

    </script>

</head>

<body>

    <form>

        <div style="margin-left: 20px;">

            <h1>File Uploader</h1>

            <p>

                <strong>SAS URI</strong>:

                <br />

                <span class="input-control text">

                    <input type="text" id="sasUrl" style="width: 50%"

                           value="" />

                </span>

            </p>

            <p>

                <strong>File To Upload</strong>:

                <br />

                <span class="input-control text">

                    <input type="file" id="file" name="file" style="width: 50%" />

                </span>

            </p>

            <div id="output">

 

                <strong>File Properties:</strong>

                <br />

                <p>

                    Name: <span id="fileName"></span>

                </p>

                <p>

                    File Size: <span id="fileSize"></span> bytes.

                </p>

                <p>

                    File Type: <span id="fileType"></span>

                </p>

                <p>

                    <input type="button" value="Upload File" onclick="uploadFileInBlocks()" />

                </p>

                <p>

                    <strong>Progress</strong>: <span id="fileUploadProgress">0.00 %</span>

                </p>

            </div>

        </div>

        <div>

        </div>

    </form>

</body>

</html>
View Code

代碼主要是將文件切成小塊,並使用Put blob操做上傳相應的小塊,最後使用Put blob list將上傳的各個小塊組成資源文件。

相關文章
相關標籤/搜索