Home
%3CLINGO-SUB%20id%3D%22lingo-sub-392687%22%20slang%3D%22en-US%22%3EAzure%20Storage%20Blob%20upload%20from%20browser%3C%2FLINGO-SUB%3E%3CLINGO-BODY%20id%3D%22lingo-body-392687%22%20slang%3D%22en-US%22%3E%0A%20%26lt%3Bmeta%20http-equiv%3D%22Content-Type%22%20content%3D%22text%2Fhtml%3B%20charset%3DUTF-8%22%20%2F%26gt%3B%3CSTRONG%3E%20First%20published%20on%20MSDN%20on%20Oct%2025%2C%202018%20%3C%2FSTRONG%3E%20%3CBR%20%2F%3E%3CP%3EMany%20web%20application%20needs%20end-users%20to%20upload%20files%20for%20processing.%20And%20these%20files%20need%20to%20be%20stored%20in%20a%20persisted%20storage.%20One%20common%20practice%20is%2C%20developers%20write%20code%20to%20upload%20the%20file%20and%20save%20it%20on%20the%20webserver%20itself.%20This%20approach%20is%20OK%20if%20the%20file%20size%20is%20small%20and%2For%20smaller%20number%20of%20uploads.%20Recommended%20approach%20is%2C%20let%20the%20browse%20upload%20the%20files%20to%20Azure%20Storage%20directly%20without%20need%20to%20talk%20to%20webserver.%20This%20option%2C%20frees%20up%20webserver%20for%20other%20business%20processing.%3C%2FP%3E%3CBR%20%2F%3E%3CP%3EFor%20browser%20to%20talk%20to%20Azure%20Storage%2C%20instead%20of%20exposing%20storage%20connection%20string%2C%20we%20can%20use%20SAS%20Key%20(Share%20Access%20Security).%20SAS%20key%20is%20valid%20only%20for%20limited%20time%20and%20has%20specific%20permissions%20like%20write%20but%20not%20read%20or%20list.%20For%20more%20details%20on%20SAS%20keys%20please%20see%20%3CA%20href%3D%22https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fstorage%2Fcommon%2Fstorage-dotnet-shared-access-signature-part-1%22%20target%3D%22_blank%22%20rel%3D%22noopener%20noreferrer%20noopener%20noreferrer%22%3E%20here%3C%2FA%3E%3C%2FP%3E%3CBR%20%2F%3E%3CP%3EHere%20is%20quick%20sample%20to%20upload%20blob%20files%20to%20Azure%20Storage%20from%20a%20browser%20directly%20and%20then%20process%20it%20the%20server%20side.%3C%2FP%3E%3CBR%20%2F%3E%20%3CBR%20%2F%3E%3COL%3E%3CBR%20%2F%3E%3CLI%3E%3CBR%20%2F%3E%20Blob%20files%20are%20uploaded%20directly%20from%20browser%20to%20Storage%20using%20SAS%20Key%3C%2FLI%3E%3CBR%20%2F%3E%3CLI%3E%3CBR%20%2F%3E%20Browser%20sends%20the%20blob%20file%20name%20to%20Web%20server%3C%2FLI%3E%3CBR%20%2F%3E%3CLI%3E%3CBR%20%2F%3E%20Web%20server%20access%20blob%20using%20connection%20string%3C%2FLI%3E%3CBR%20%2F%3E%3C%2FOL%3E%3CBR%20%2F%3E%3CP%3E%3CIMG%20src%3D%22https%3A%2F%2Ftechcommunity.microsoft.com%2Ft5%2Fimage%2Fserverpage%2Fimage-id%2F101276i276C7F40A2A937ED%22%20%2F%3E%3C%2FP%3E%3CBR%20%2F%3E%20%3CBR%20%2F%3E%3CH2%20id%3D%22toc-hId-1681587593%22%20id%3D%22toc-hId-1701904089%22%3E1.%20Download%20JavaScript%20Client%20library%20for%20Azure%20Storage%3C%2FH2%3E%3CBR%20%2F%3E%3CUL%3E%3CBR%20%2F%3E%3CLI%3EDownload%20the%20zip%20from%20%3CA%20href%3D%22https%3A%2F%2Faka.ms%2Fdownloadazurestoragejs%22%20title%3D%22https%3A%2F%2Faka.ms%2Fdownloadazurestoragejs%22%20target%3D%22_blank%22%20rel%3D%22noopener%20noreferrer%20noopener%20noreferrer%22%3E%20https%3A%2F%2Faka.ms%2Fdownloadazurestoragejs%3C%2FA%3E%3C%2FLI%3E%3CBR%20%2F%3E%3CLI%3EMore%20details%20on%20this%20client%20library%20is%20found%20%3CA%20href%3D%22https%3A%2F%2Fazure.microsoft.com%2Fen-us%2Fblog%2Fnew-azure-storage-javascript-client-library-for-browsers-preview%2F%22%20target%3D%22_blank%22%20rel%3D%22noopener%20noreferrer%20noopener%20noreferrer%22%3E%20here%20%3C%2FA%3E%20and%20%3CA%20href%3D%22https%3A%2F%2Fdmrelease.blob.core.windows.net%2Fazurestoragejssample%2Fsamples%2Fsample-blob.html%23step2%22%20target%3D%22_blank%22%20rel%3D%22nofollow%20noopener%20noreferrer%20noopener%20noreferrer%22%3E%20here%3C%2FA%3E%3C%2FLI%3E%3CBR%20%2F%3E%3C%2FUL%3E%3CBR%20%2F%3E%3CH2%20id%3D%22toc-hId--870569368%22%20id%3D%22toc-hId--850252872%22%3E2.%20Generate%20SAS%20token%3C%2FH2%3E%3CBR%20%2F%3E%3COL%3E%3CBR%20%2F%3E%3CLI%3E%3CBR%20%2F%3E%20Log%20into%20Azure%20portal%20%3CA%20href%3D%22https%3A%2F%2Fportal.Azure.com%22%20target%3D%22_blank%22%20rel%3D%22nofollow%20noopener%20noreferrer%20noopener%20noreferrer%22%3E%20https%3A%2F%2Fportal.Azure.com%3C%2FA%3E%3C%2FLI%3E%3CBR%20%2F%3E%3CLI%3E%3CBR%20%2F%3E%20Navigate%20to%20your%20Storage%20Account%3C%2FLI%3E%3CBR%20%2F%3E%3CLI%3E%3CBR%20%2F%3E%20Click%20on%20the%20%3CSTRONG%3E%20Share%20Access%20Signature%3C%2FSTRONG%3E%3C%2FLI%3E%3CBR%20%2F%3E%3CLI%3E%3CBR%20%2F%3E%20Select%20write%20only%20as%20shown%20below%20and%20click%20Generate%20SAS%20token%20button%3C%2FLI%3E%3CBR%20%2F%3E%3CLI%3E%3CBR%20%2F%3E%20Copy%20SAS%20token%3C%2FLI%3E%3CBR%20%2F%3E%3CLI%3E%3CBR%20%2F%3E%20Note%20%3A%20you%20may%20have%20to%20change%20expiry%20date%2Ftime%20if%20you%20are%20planning%20to%20use%20this%20SAS%20key%20for%20longer%20duration%20%3CBR%20%2F%3E%3CDIV%3E%3CIMG%20src%3D%22https%3A%2F%2Ftechcommunity.microsoft.com%2Ft5%2Fimage%2Fserverpage%2Fimage-id%2F101277i8E578EA30D3E49BC%22%20%2F%3E%3C%2FDIV%3E%0A%20%20%20%3C%2FLI%3E%3CBR%20%2F%3E%3C%2FOL%3E%3CBR%20%2F%3E%3CH2%20id%3D%22toc-hId-872240967%22%20id%3D%22toc-hId-892557463%22%3E3.%20Enable%20CORS%3C%2FH2%3E%3CBR%20%2F%3E%3COL%3E%3CBR%20%2F%3E%3CLI%3E%3CBR%20%2F%3E%20Log%20into%20Azure%20Portal%20%3CA%20href%3D%22https%3A%2F%2Fportal.azure.com%22%20target%3D%22_blank%22%20rel%3D%22nofollow%20noopener%20noreferrer%20noopener%20noreferrer%22%3E%20https%3A%2F%2Fportal.azure.com%3C%2FA%3E%3C%2FLI%3E%3CBR%20%2F%3E%3CLI%3E%3CBR%20%2F%3E%3CDIV%3ENavigate%20to%20your%20Azure%20Storage%20account%3C%2FDIV%3E%0A%20%20%20%3C%2FLI%3E%3CBR%20%2F%3E%3CLI%3E%3CBR%20%2F%3E%3CDIV%3EClick%20on%20CORS%3C%2FDIV%3E%0A%20%20%20%3C%2FLI%3E%3CBR%20%2F%3E%3CLI%3E%3CBR%20%2F%3E%20Set%20these%20following%20values%20and%20hit%20Save%20button%20%3CBR%20%2F%3E%3CDIV%3E%3CIMG%20src%3D%22https%3A%2F%2Ftechcommunity.microsoft.com%2Ft5%2Fimage%2Fserverpage%2Fimage-id%2F101278iC052A5A82621FD0E%22%20%2F%3E%3C%2FDIV%3E%0A%20%20%20%3C%2FLI%3E%3CBR%20%2F%3E%3C%2FOL%3E%3CBR%20%2F%3E%3CH2%20id%3D%22toc-hId--1679915994%22%20id%3D%22toc-hId--1659599498%22%3E4.%20Client%20side%20code%3C%2FH2%3E%3CBR%20%2F%3E%3COL%3E%3CBR%20%2F%3E%3CLI%3EExtract%20the%20above%20zip%20file%20and%20copy%20the%20%3CSTRONG%3E%20azure-storage.blob.min.js%20%3C%2FSTRONG%3E%20to%20your%20application%20scripts%20folder.%20For%20ASP.NET%20MVC%20application%2C%20you%20can%20copy%20it%20to%20%3CSTRONG%3E%20Script%20%3C%2FSTRONG%3E%20folder%20as%20shown%20below%20%3CBR%20%2F%3E%3CP%3E%3C%2FP%3E%0A%20%20%20%20%3CDIV%3E%3CIMG%20src%3D%22https%3A%2F%2Ftechcommunity.microsoft.com%2Ft5%2Fimage%2Fserverpage%2Fimage-id%2F101279iACCEA8DA1C726B10%22%20%2F%3E%3C%2FDIV%3E%3CBR%20%2F%3E%3C%2FLI%3E%3CBR%20%2F%3E%3CLI%3EIn%20your%20client%20side%20code%2C%20add%20these%20lines%20%3CBR%20%2F%3E%20%5Bcode%20language%3D%22javascript%22%5D%20%3CBR%20%2F%3E%20%3CBR%20%2F%3E%2F%2Fthis%20Azure%20Storage%20JavaScript%20Client%20Library%3CBR%20%2F%3E%20%3CBR%20%2F%3E%20%3CBR%20%2F%3E%3CP%3ESelect%20file%20to%20upload%20to%20blob%3C%2FP%3E%3CBR%20%2F%3E%3CP%3E%3CBR%20%2F%3E%20%3CBR%20%2F%3E%3C%2FP%3E%3CBR%20%2F%3E%3CP%3E%3CBR%20%2F%3E%20Upload%20to%20blob%20%3CBR%20%2F%3E%3C%2FP%3E%3CBR%20%2F%3E%3CP%3E%3CBR%20%2F%3E%20Do%20server%20side%20processing%20%3CBR%20%2F%3E%3C%2FP%3E%3CBR%20%2F%3E%20%3CBR%20%2F%3E%20%3CBR%20%2F%3E%3CBR%20%2F%3E%20var%20blobname%3B%3CBR%20%2F%3E%20function%20blobUpload()%20%7B%3CBR%20%2F%3E%20%2F%2F%20blob%20client%3CBR%20%2F%3E%20var%20blobUri%20%3D%20'%3CA%20href%3D%22https%3A%2F%2FSTORAGENAME.blob.core.windows.net'%3B%26lt%3Bbr%2F%22%20target%3D%22_blank%22%20rel%3D%22nofollow%20noopener%20noreferrer%20noopener%20noreferrer%22%3Ehttps%3A%2F%2FSTORAGENAME.blob.core.windows.net'%3B%3CBR%20%2F%3E%26gt%3B%20var%20blobService%20%3D%20AzureStorage.Blob.createBlobServiceWithSas(blobUri%2C%20'SASKEY')%3B%3CBR%20%2F%3E%3CBR%20%2F%3E%20%2F%2F%20blob%20upload%3CBR%20%2F%3E%20var%20file%20%3D%20document.getElementById('blobFile').files%5B0%5D%3B%3CBR%20%2F%3E%3CBR%20%2F%3E%20var%20customBlockSize%20%3D%20file.size%20%26gt%3B%201024%20*%201024%20*%2032%20%3F%201024%20*%201024%20*%204%20%3A%201024%20*%20512%3B%3CBR%20%2F%3E%20blobService.singleBlobPutThresholdInBytes%20%3D%20customBlockSize%3B%3CBR%20%2F%3E%3CBR%20%2F%3E%20var%20filename%20%3D%20file.name.substring(0%2C%20file.name.lastIndexOf('.'))%3B%3CBR%20%2F%3E%20var%20ext%20%3D%20file.name.substring(file.name.lastIndexOf('.'))%3B%3CBR%20%2F%3E%3CBR%20%2F%3E%20blobname%20%3D%20filename%20%2B%20'_'%20%2B%20Math.random().toString(16).slice(2)%20%2B%20ext%3B%3CBR%20%2F%3E%3CBR%20%2F%3E%20var%20speedSummary%20%3D%20blobService.createBlockBlobFromBrowserFile('CONTAINER'%2C%20blobname%2C%20file%2C%20%7B%20blockSize%3A%20customBlockSize%20%7D%2C%20function%20(error%2C%20result%2C%20response)%20%7B%3CBR%20%2F%3E%20if%20(error)%20%7B%3CBR%20%2F%3E%20%2F%2F%20Upload%20blob%20failed%3CBR%20%2F%3E%20alert(%22blob%20upload%20failed%20%3A%20check%20CORS%22)%3B%3CBR%20%2F%3E%20%7D%20else%20%7B%3CBR%20%2F%3E%20%2F%2F%20Upload%20successfully%3CBR%20%2F%3E%20alert(%22blob%20upload%20successfull%22)%3B%3CBR%20%2F%3E%20%7D%3CBR%20%2F%3E%20%7D)%3B%3CBR%20%2F%3E%3CBR%20%2F%3E%20var%20bcheckList%20%3D%20false%3B%3CBR%20%2F%3E%20if%20(bcheckList)%20%7B%3CBR%20%2F%3E%20%2F%2F%20blob%20list%3CBR%20%2F%3E%20blobService.listBlobsSegmented('CONTAINER'%2C%20null%2C%20function%20(error%2C%20results)%20%7B%3CBR%20%2F%3E%20if%20(error)%20%7B%3CBR%20%2F%3E%20%2F%2F%20List%20blobs%20error%3CBR%20%2F%3E%20alert(%22blob%20list%20failed%20%3A%20check%20SAS%20token%22)%3B%3CBR%20%2F%3E%20%7D%20else%20%7B%3CBR%20%2F%3E%20for%20(var%20i%20%3D%200%2C%20blob%3B%20blob%20%3D%20results.entries%5Bi%5D%3B%20i%2B%2B)%20%7B%3CBR%20%2F%3E%20%2F%2F%20blob%20object%3CBR%20%2F%3E%20alert(%22blob%20found%20%3A%20%22%20%2B%20blob)%3B%3CBR%20%2F%3E%20%7D%3CBR%20%2F%3E%20%7D%3CBR%20%2F%3E%20%7D)%3B%3CBR%20%2F%3E%20%7D%3CBR%20%2F%3E%20%7D%3CBR%20%2F%3E%3CBR%20%2F%3E%20function%20serverside()%20%7B%3CBR%20%2F%3E%20var%20newURL%20%3D%20location.protocol%20%2B%20%22%2F%2F%22%20%2B%20location.host%20%2B%20%22%2FHome%2FContact%3Fid%3D%22%20%2B%20blobname%3B%3CBR%20%2F%3E%20newURL%20%3D%20encodeURI(newURL)%3CBR%20%2F%3E%20%2F%2Falert(newURL)%3B%3CBR%20%2F%3E%20window.location%20%3D%20newURL%3B%3CBR%20%2F%3E%20%7D%3CBR%20%2F%3E%3CBR%20%2F%3E%20%3CBR%20%2F%3E%20%3CBR%20%2F%3E%20%5B%2Fcode%5D%20%3CBR%20%2F%3E%3C%2FA%3E%3C%2FLI%3E%3CBR%20%2F%3E%20%3CBR%20%2F%3E%3C%2FOL%3E%3CBR%20%2F%3E%3CH2%20id%3D%22toc-hId-62894341%22%20id%3D%22toc-hId-83210837%22%3E5.%20Server%20side%20code%3C%2FH2%3E%3CBR%20%2F%3E%3COL%3E%3CBR%20%2F%3E%3CLI%3EAdd%20following%20code%20on%20your%20server%20side%20%3CBR%20%2F%3E%20%5Bcode%20language%3D%22csharp%22%5D%20%3CBR%20%2F%3E%20public%20ActionResult%20Contact(string%20id)%20%3CBR%20%2F%3E%20%7B%20%3CBR%20%2F%3E%20%2F%2F%20id%20is%20blob%20file%20name%20%3CBR%20%2F%3E%20CloudStorageAccount%20storageAccount%20%3D%20null%3B%20%3CBR%20%2F%3E%20%3CBR%20%2F%3E%20CloudBlobContainer%20cloudBlobContainer%20%3D%20null%3B%20%3CBR%20%2F%3E%20%3CBR%20%2F%3E%20var%20storageConnectionString%20%3D%20%22CONNECTION%20STRING%20TO%20STORAGE%22%3B%20%3CBR%20%2F%3E%20CloudStorageAccount.TryParse(storageConnectionString%2C%20out%20storageAccount)%3B%20%3CBR%20%2F%3E%20%3CBR%20%2F%3E%20CloudBlobClient%20cloudBlobClient%20%3D%20storageAccount.CreateCloudBlobClient()%3B%20%3CBR%20%2F%3E%20%3CBR%20%2F%3E%20cloudBlobContainer%20%3D%20cloudBlobClient.GetContainerReference(%22CONTAINER%22)%3B%20%3CBR%20%2F%3E%20%3CBR%20%2F%3E%20CloudBlockBlob%20cloudBlockBlob%20%3D%20cloudBlobContainer.GetBlockBlobReference(id)%3B%20%3CBR%20%2F%3E%20%3CBR%20%2F%3E%20ViewBag.Message%20%3D%20%22Your%20contact%20page.%22%3B%20%3CBR%20%2F%3E%20%3CBR%20%2F%3E%20return%20View()%3B%20%3CBR%20%2F%3E%20%7D%20%3CBR%20%2F%3E%20%5B%2Fcode%5D%20%3CBR%20%2F%3E%3C%2FLI%3E%3CBR%20%2F%3E%3C%2FOL%3E%0A%20%0A%3C%2FLINGO-BODY%3E%3CLINGO-TEASER%20id%3D%22lingo-teaser-392687%22%20slang%3D%22en-US%22%3EFirst%20published%20on%20MSDN%20on%20Oct%2025%2C%202018%20Many%20web%20application%20needs%20end-users%20to%20upload%20files%20for%20processing.%3C%2FLINGO-TEASER%3E
Microsoft
First published on MSDN on Oct 25, 2018

Many web application needs end-users to upload files for processing. And these files need to be stored in a persisted storage. One common practice is, developers write code to upload the file and save it on the webserver itself. This approach is OK if the file size is small and/or smaller number of uploads. Recommended approach is, let the browse upload the files to Azure Storage directly without need to talk to webserver. This option, frees up webserver for other business processing.


For browser to talk to Azure Storage, instead of exposing storage connection string, we can use SAS Key (Share Access Security). SAS key is valid only for limited time and has specific permissions like write but not read or list. For more details on SAS keys please see here


Here is quick sample to upload blob files to Azure Storage from a browser directly and then process it the server side.





  1. Blob files are uploaded directly from browser to Storage using SAS Key


  2. Browser sends the blob file name to Web server


  3. Web server access blob using connection string




1. Download JavaScript Client library for Azure Storage



2. Generate SAS token




  1. Log into Azure portal https://portal.Azure.com


  2. Navigate to your Storage Account


  3. Click on the Share Access Signature


  4. Select write only as shown below and click Generate SAS token button


  5. Copy SAS token


  6. Note : you may have to change expiry date/time if you are planning to use this SAS key for longer duration


3. Enable CORS




  1. Log into Azure Portal https://portal.azure.com


  2. Navigate to your Azure Storage account


  3. Click on CORS


  4. Set these following values and hit Save button


4. Client side code



  1. Extract the above zip file and copy the azure-storage.blob.min.js to your application scripts folder. For ASP.NET MVC application, you can copy it to Script folder as shown below



  2. In your client side code, add these lines
    [code language="javascript"]
    <br/>//this Azure Storage JavaScript Client Library<br/>

    Select file to upload to blob






    Upload to blob



    Do server side processing



    <br/><br/> var blobname;<br/> function blobUpload() {<br/> // blob client<br/> var blobUri = 'https://STORAGENAME.blob.core.windows.net';<br/> var blobService = AzureStorage.Blob.createBlobServiceWithSas(blobUri, 'SASKEY');<br/><br/> // blob upload<br/> var file = document.getElementById('blobFile').files[0];<br/><br/> var customBlockSize = file.size > 1024 * 1024 * 32 ? 1024 * 1024 * 4 : 1024 * 512;<br/> blobService.singleBlobPutThresholdInBytes = customBlockSize;<br/><br/> var filename = file.name.substring(0, file.name.lastIndexOf('.'));<br/> var ext = file.name.substring(file.name.lastIndexOf('.'));<br/><br/> blobname = filename + '_' + Math.random().toString(16).slice(2) + ext;<br/><br/> var speedSummary = blobService.createBlockBlobFromBrowserFile('CONTAINER', blobname, file, { blockSize: customBlockSize }, function (error, result, response) {<br/> if (error) {<br/> // Upload blob failed<br/> alert("blob upload failed : check CORS");<br/> } else {<br/> // Upload successfully<br/> alert("blob upload successfull");<br/> }<br/> });<br/><br/> var bcheckList = false;<br/> if (bcheckList) {<br/> // blob list<br/> blobService.listBlobsSegmented('CONTAINER', null, function (error, results) {<br/> if (error) {<br/> // List blobs error<br/> alert("blob list failed : check SAS token");<br/> } else {<br/> for (var i = 0, blob; blob = results.entries[i]; i++) {<br/> // blob object<br/> alert("blob found : " + blob);<br/> }<br/> }<br/> });<br/> }<br/> }<br/><br/> function serverside() {<br/> var newURL = location.protocol + "//" + location.host + "/Home/Contact?id=" + blobname;<br/> newURL = encodeURI(newURL)<br/> //alert(newURL);<br/> window.location = newURL;<br/> }<br/><br/>

    [/code]



5. Server side code



  1. Add following code on your server side
    [code language="csharp"]
    public ActionResult Contact(string id)
    {
    // id is blob file name
    CloudStorageAccount storageAccount = null;

    CloudBlobContainer cloudBlobContainer = null;

    var storageConnectionString = "CONNECTION STRING TO STORAGE";
    CloudStorageAccount.TryParse(storageConnectionString, out storageAccount);

    CloudBlobClient cloudBlobClient = storageAccount.CreateCloudBlobClient();

    cloudBlobContainer = cloudBlobClient.GetContainerReference("CONTAINER");

    CloudBlockBlob cloudBlockBlob = cloudBlobContainer.GetBlockBlobReference(id);

    ViewBag.Message = "Your contact page.";

    return View();
    }
    [/code]