UNPKG

azure-storage

Version:

Microsoft Azure Storage Client Library for Node.js

576 lines (516 loc) 31.1 kB
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <title>Azure Storage JavaScript Client Library Sample for File Operations</title> <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.0/css/bootstrap.min.css"> </head> <body> <div class="container"> <div class="mt-1"> <h1>Azure Storage JavaScript Client Library Sample for File Operations</h1> </div> <p class="lead">In this sample, we will demonstrate common scenarios for Azure File Storage that includes creating, listing and deleting file shares, directories and files.</p> <hr/> <p>Azure File storage is a service for storing large amounts of unstructured object data, such as text or binary data, that can be accessed from anywhere in the world via HTTP or HTTPS. You can use file storage to expose data publicly to the world, or to store application data privately.</p> <p>With Azure File storage, you can migrate legacy applications that rely on file shares to Azure quickly and without costly rewrites. Applications running in Azure virtual machines or cloud services or from on-premises clients can mount a file share in the cloud, just as a desktop application mounts a typical SMB share. Any number of application components can then mount and access the File storage share simultaneously. In this sample, you are able to create a file service with storage account and SAS Token. Based on the file service, you could create a file share, list files, upload files and delete files.</p> <div class="panel panel-danger"> <div class="panel-body"> <b>Note</b>: You may need set up a HTTP server to host this sample for IE11 and latest Chrome. </div> </div> <h2>Contents:</h2> <ul> <li><a href="#step1">Step 1: Preparing an Azure Storage account with CORS rules set</a></li> <li><a href="#step2">Step 2: Importing Azure Storage JavaScript Client Library</a></li> <li><a href="#step3">Step 3: Creating an Azure Storage File Service Object</a></li> <li><a href="#step4">Step 4: File Operations</a></li> <li><a href="#step5">Step 5: Directory and File Operations</a></li> <li><a href="#step6">Step 6: Creating your JavaScript Application based on Azure Storage JavaScript Client Library</a></li> </ul> <h2 id="step1">Step 1: Preparing an Azure Storage account with CORS rules set</h2> <p>Cross-origin resource sharing, or CORS, must be configured on the Azure Storage account to be accessed directly from JavaScript in the browser. You are able to set the CORS rules for specific Azure Storage account on the <a href="https://portal.azure.com">Azure Portal</a>. The "Allowed origins" could be set to "*" to allow all the origins in this sample. For more information about CORS, see <a href="https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/cross-origin-resource-sharing--cors--support-for-the-azure-storage-services">Cross-Origin Resource Sharing (CORS)</a>.</p> <img src="cors.PNG"/> <h2 id="step2">Step 2: Importing Azure Storage JavaScript Files</h2> <p> Importing <code>azure-storage.file.js</code> in your HTML file for file operations. <p> <pre> &lt;script src="azure-storage.file.js"&gt;&lt;/script&gt; </pre> <h2 id="step3">Step 3: Creating an Azure Storage File Service Object</h2> <p> The <code>FileService</code> object lets you work with files and directories. Following code creates a <code>FileService</code> object with storage account and SAS Token. </p> <pre> var fileUri = 'https://' + 'STORAGE_ACCOUNT' + '.file.core.windows.net'; var fileService = AzureStorage.File.createFileServiceWithSas(fileUri, 'SAS_TOKEN'); </pre> <p> You can load Azure Storage JavaScript Client Library in a CommonJS or AMD environment by JavaScript module loaders. If no module system is found, global variable <code>AzureStorage.File</code> will be set, which is the start point where we can create service objects for file and access to the storage utilities. </p> <div class="panel panel-primary"> <div class="panel-body"> <b>How to get full detailed API definitions? </b> Currently, the JavaScript Client Library shares almost the same API definitions with Node.js SDK, besides Node.js runtime specific APIs. Please check API details on <a href="http://azure.github.io/azure-storage-node/">Azure Storage API reference documents</a>. The JavaScript global variable <code>AzureStorage.File</code> is just like the object <code>require('azure-storage')</code> returns in Node.js, but limits to File related interfaces. Go to <a href="https://azure.github.io/azure-storage-node/FileService.html">FileService</a> to view possible methods provided by <code>FileService</code> class. </div> </div> <div class="panel panel-danger"> <div class="panel-body"> <b>Warning</b>: Azure Storage JavaScript Client Library also supports creating <code>FileService</code> based on Storage Account Key for authentication besides SAS Token. However, for security concerns, we recommend use of a limited time SAS Token, generated by a backend web server using a <a href="https://docs.microsoft.com/en-us/azure/storage/storage-dotnet-shared-access-signature-part-1">Stored Access Policy</a>. </div> </div> <h2 id="step4">Step 4: File Share Operations</h2> <p><b>Share</b>: A File storage share is an SMB file share in Azure. All directories and files must be created in a parent share. An account can contain an unlimited number of shares, and a share can store an unlimited number of files, up to the 5 TB total capacity of the file share.</p> <h3>List File Shares</h3> <p><code>FileService</code> provides <code>listSharesSegmented</code> and <code>listSharesSegmentedWithPrefix</code> for listing file shares under a storage account.</p> <pre> fileService.listSharesSegmented(null, function(error, result) { if(error) { // List shares error } else { for (var i = 0, share; share = results.entries[i]; i++) { // Deal with share object } } }); </pre> <h3>Create File Share</h3> <p><code>FileService</code> provides <code>createShare</code> and <code>createShareIfNotExists</code> for creating a file share under a storage account.</p> <pre> fileService.createShareIfNotExists('myshare', function(error, result) { if(error) { // Create share error } else { // Create share successfully } }); </pre> <h3>Delete File Share</h3> <p><code>FileService</code> provides <code>deleteShare</code> and <code>deleteShareIfExists</code> for deleting a file share under a storage account.</p> <pre> fileService.deleteShareIfExists('myshare', function(error, result) { if(error) { // Delete share error } else { // Delete share successfully } }); </pre> <h3>Executable Example</h3> <p>The sample will try to create an Azure Storage file service object based on SAS Token authorization. Enter your Azure Storage account name and SAS Token here. Make sure you have set the CORS rules for the Azure Storage file service, and the SAS Token is in valid period.</p> <label><b>Storage account:</b> </label> <input type="text" id="account"/> <label><b>SAS Token:</b> </label> <input type="text" id="sas"/> <p> Azure Storage file service provides plenty of interfaces for file operations. In following example, you can try to list all the file shares under your storage account, and try to create or delete one file share from your account.</p> <ul> <li><p> Click <button class="btn btn-xs btn-primary" onclick="refreshFileShareList()">ListFileShares</button> button to view the file share list under your Azure Storage account</p></li> <li> <p> Click <button class="btn btn-xs btn-primary" onclick="createFileShare()">CreateFileShare</button> button to create a file share under your Azure Storage account</p> <p><label><b>New File Share Name:</b> </label> <input type="text" value="myfileshare" id="newfileshare"/> </p> </li> <li><p> Click "<b>Delete</b>" button to delete the file share under your Azure Storage account</p></li> <li><p> Click "<b>Select</b>" button to operate with the directories and files in next step</p></li> </ul> <div id="result"></div> <h2 id="step5">Step 5: Directory and File Operations</h2> <p><b>Directory</b> in storage is an optional hierarchy of directories.</p> <p><b>File</b>: A file in the share. A file may be up to 1 TB in size.</p> <h3>List Files and Directories</h3> <p><code>FileService</code> provides <code>listFilesAndDirectoriesSegmented</code> for listing directories and files under a file share.</p> <pre> fileService.listFilesAndDirectoriesSegmented('myfileshare', '', null, function(error, result, response) { if(error) { // List table entity error } else { for (var i = 0, dir; dir = results.entries.directories[i]; i++) { // Deal with directory object } for (var i = 0, file; file = results.entries.files[i]; i++) { // Deal with file object } } }); </pre> <h3>Create Directory</h3> <p><code>FileService</code> provides <code>createDirectory</code> and <code>createDirectoryIfNotExists</code> for creating directories under a file share.</p> <pre> fileService.createDirectoryIfNotExists('myfileshare', 'mydirectory', function(error, result, response) { if(error) { // Create directory error } else { // Create directory successfully } }); </pre> <h3>Delete Directory</h3> <p><code>FileService</code> provides <code>deleteDirectory</code> and <code>deleteDirectoryIfExists</code> for deleting directories under a file share.</p> <pre> fileService.deleteDirectoryIfExists('myfileshare', 'mydirectory', function(error, result, response) { if(error) { // Delete directory error } else { // Delete directory successfully } }); </pre> <h3>Upload File</h3> <p><code>FileService</code> provides <code>createFileFromBrowserFile</code> for uploading a file from an HTML file in browsers. </p> <p>Uploading file from stream. You can set up the file name as well as the size of this uploading session. </p> <pre> // If one file has been selected in the HTML file input element var files = document.getElementById('fileinput').files; var file = files[0]; var finishedOrError = false; var speedSummary = fileService.createFileFromBrowserFile('myfileshare', 'mydirectory', file.name, file, {}, function(error, result, response) { finishedOrError = true; if (error) { // Upload file failed } else { // Upload successfully } }); refreshProgress(); </pre> <p>Checking the upload progress with speedSummary object. </p> <pre> speedSummary.on('progress', function () { var process = speedSummary.getCompletePercent(); displayProcess(process); }); </pre> <h3>Download File</h3> <p> <code>FileService</code> provides interfaces for downloading a file into browser memory directly. Because of browser's sandbox limitation, we cannot save the downloaded data trunks into disk until we get all the data trunks of a file into browser memory. The browser's memory size is also limited especially for downloading huge files, so it's recommended to download a file in browser with SAS Token authorized link directly. </p> <p> Shared access signatures (SAS) are a secure way to provide granular access to files and directories without providing your storage account name or keys. Shared access signatures are often used to provide limited access to your data, such as allowing a mobile app to access files. The following code example generates a new shared access policy that allows the shared access signatures holder to perform read operations on the myfile file, and expires 100 minutes after the time it is created. </p> <div class="panel panel-primary"> <div class="panel-body"> <b>Note: </b> You can choose to use the SAS Token in browser side, or generate a temporary SAS Token dynamically in your server side with Azure Storage C# or Node.js SDKs etc. according to your security requirements. </div> </div> <pre> var downloadLink = fileService.getUrl('myshare', 'mydirectory', 'myfile', 'SAS_TOKEN'); </pre> <h3>Delete File</h3> <p><code>FileService</code> provides <code>deleteFile</code> and <code>deleteFileIfExists</code> for deleting files under a file share.</p> <pre> fileService.deleteFileIfExists('myfileshare', 'mydirectory', 'myfile', function(error, result, response) { if(error) { // Delete file error } else { // Delete file successfully } }); </pre> <h3>Executable Example</h3> <p>After clicked the "<b>Select</b>" button on the file share list, you are able to operate with the directories and files under the selected file share.<p> <ul> <li><p> Click <button class="btn btn-xs btn-primary" onclick="refreshDirectoryFileList()">ListFilesAndDirectories</button> button to view the directories and files under your selected file share</p></li> <li><p> Click <button class="btn btn-xs btn-primary" onclick="createDirectory()">CreateDirectory</button> button to create a directory share under your current directory</p> <p><label><b>New Directory Name:</b> </label> <input type="text" value="mydirectory" id="newdirectory"/> </p> </li> <li><p> Click <button class="btn btn-xs btn-primary" onclick="backDirectory()">GoToUpperDirectory</button> button to return to upper level directory</p></li> <li><p> Click <button id="upload-button" class="btn btn-xs btn-primary" onclick="createFileFromStream(false)">Upload</button> button to upload a local file to current directory</p> <p><input type="file" id="files" name="file" onclick="displayProcess(0)" /></p></li> <li><p> Click "<b>Delete</b>" button to delete the directory or file</p></li> <li><p> Click "<b>Download</b>" link to download a file to local</p></li> </ul> <b>Current Path:<a id="path"></a></b> <div> Uploaded Bytes: <font id="read"> </font> </div> <div class="progress"> <div id="progress" class="progress-bar" role="progressbar" aria-valuenow="60" aria-valuemin="0" aria-valuemax="100" style="width: 0%;"> 0% </div> </div> <div id="directoryFiles"></div> <h3 id="step6">Step 6: Creating your JavaScript Application based on Azure Storage JavaScript Client Library</h3> <ol> <li>Setting CORS rules for your selected Azure-Storage account file service.</li> <li>Including functional file(s) needed, such as "azure-storage.file.js" for file operation.</li> <li>Using keyword "AzureStorage.File" to access to Azure storage JavaScript APIs for files.</li> <li>Referring to <a href="http://azure.github.io/azure-storage-node/">API documents</a> for detailed API definitions.</li> </ol> <p> You can view the source code of this sample for detailed reference. </p> </div> <script src="../bundle/azure-storage.file.js"></script> <script> var account = document.getElementById('account').value; var sas = document.getElementById('sas').value; var fileShare = ''; var currentPath = ''; var fileUri = ''; var currentPath = []; function checkParameters() { account = document.getElementById('account').value; sas = document.getElementById('sas').value; if (account == null || account.length < 1) { alert('Please enter a valid storage account name!'); return false; } if (sas == null || sas.length < 1) { alert('Please enter a valid SAS Token!'); return false; } return true; } function getFileService() { if (!checkParameters()) return null; fileUri = 'https://' + account + '.file.core.windows.net'; var fileService = AzureStorage.File.createFileServiceWithSas(fileUri, sas).withFilter(new AzureStorage.File.ExponentialRetryPolicyFilter()); return fileService; } function refreshFileShareList() { var fileService = getFileService(); if (!fileService) return; document.getElementById('result').innerHTML = 'Loading...'; fileService.listSharesSegmented(null, function (error, results) { if (error) { alert('List file share error, please open browser console to view detailed error'); console.log(error); } else { var output = []; output.push('<tr>', '<th>ShareName</th>', '<th>ShareETag</th>', '<th>ShareQuota</th>', '<th>LastModified</th>', '<th>Operations</th>', '</tr>'); if (results.entries.length < 1) { output.push('<tr><td>Empty results...</td></tr>'); } for (var i = 0, share; share = results.entries[i]; i++) { output.push('<tr>', '<td>', share.name, '</td>', '<td>', share.etag, '</td>', '<td>', share.quota, '</td>', '<td>', share.lastModified, '</td>', '<td>', '<button class="btn btn-xs btn-danger" onclick="deleteFileShare(\'', share.name ,'\')">Delete</button> ', '<button class="btn btn-xs btn-success" onclick="viewFileShare(\'', share.name ,'\')">Select</button>', '</td>', '</tr>'); } document.getElementById('result').innerHTML = '<table class="table table-condensed table-bordered">' + output.join('') + '</table>'; } }); } function deleteFileShare(name) { var fileService = getFileService(); if (!fileService) return; fileService.deleteShareIfExists(name, function(error, result){ if (error) { alert('Delete file share failed, open browser console for more detailed info.'); console.log(error); } else { alert('Delete ' + name + ' successfully!'); refreshFileShareList(); } }); } function createFileShare() { var fileService = getFileService(); if (!fileService) return; var share = document.getElementById('newfileshare').value; if (!AzureStorage.File.Validate.shareNameIsValid(share, function(err, res){})) { alert('Invalid share name!'); return; } fileService.createShareIfNotExists(share, function(error, result){ if (error) { alert('Create file share failed, open browser console for more detailed info.'); console.log(error); } else { alert('Create ' + share + ' successfully!'); refreshFileShareList(); } }); } function viewFileShare(selectedFileShare) { fileShare = selectedFileShare; alert('Selected ' + fileShare + ' !'); currentPath = []; refreshDirectoryFileList(); } function backDirectory() { var fileService = getFileService(); if (!fileService) return; if (fileShare.length < 1) { alert('Please select one file share!'); return; } if (currentPath.length > 0) currentPath.pop(); refreshDirectoryFileList(); } function refreshDirectoryFileList(directory) { var fileService = getFileService(); if (!fileService) return; if (fileShare.length < 1) { alert('Please select one file share!'); return; } if (typeof directory === 'undefined') var directory = ''; if (directory.length > 0) currentPath.push(directory); directory = currentPath.join('\\\\'); document.getElementById('directoryFiles').innerHTML = 'Loading...'; fileService.listFilesAndDirectoriesSegmented(fileShare, directory, null, function (error, results) { if (error) { alert('List directories and files error, please open browser console to view detailed error'); console.log(error); } else { document.getElementById('path').innerHTML = directory; var outputDirectory = []; outputDirectory.push('<tr>', '<th>Type</th>', '<th>Name</th>', '<th>ContentLength</th>', '<th>Operations</th>', '</tr>'); if (results.entries.directories.length < 1 && results.entries.files.length < 1) { outputDirectory.push('<tr><td>Empty results...</td></tr>'); } for (var i = 0, dir; dir = results.entries.directories[i]; i++) { outputDirectory.push('<tr>', '<td>', 'DIR', '</td>', '<td>', dir.name, '</td>', '<td>', dir.contentLength, '</td>', '<td>', '<button class="btn btn-xs btn-danger" onclick="deleteDirectory(\'', dir.name ,'\')">Delete</button> ', '<button class="btn btn-xs btn-success" onclick="refreshDirectoryFileList(\'', dir.name ,'\')">View</button>', '</td>', '</tr>'); } var outputFiles = []; var currentDir = currentPath.join('\\'); if (currentPath.length > 0) currentDir += '/'; for (var i = 0, file; file = results.entries.files[i]; i++) { outputFiles.push('<tr>', '<td>', 'FILE', '</td>', '<td>', file.name, '</td>', '<td>', file.contentLength, '</td>', '<td>', '<button class="btn btn-xs btn-danger" onclick="deleteFile(\'', file.name ,'\')">Delete</button> ', '<a class="btn btn-xs btn-success" href="', fileUri + '/' + fileShare + '/' + currentDir + file.name + sas, '" download>Download</a>' , '</td>', '</tr>'); } document.getElementById('directoryFiles').innerHTML = '<table class="table table-condensed table-bordered">' + outputDirectory.join('') + outputFiles.join('') + '</table>'; } }); } function deleteDirectory(name) { var fileService = getFileService(); if (!fileService) return; if (fileShare.length < 1) { alert('Please select a file share!'); return; } fileService.deleteDirectoryIfExists(fileShare, currentPath.join('\\\\') + '\\' + name, function(error, results) { if (error) { alert('Delete directory failed, open browser console for more detailed info.'); console.log(error); } else { alert('Delete ' + name + ' successfully!'); refreshDirectoryFileList(); } }); } function deleteFile(file) { var fileService = getFileService(); if (!fileService) return; fileService.deleteFileIfExists(fileShare, currentPath.join('\\\\'), file, function(error, results) { if (error) { alert('Delete file failed, open browser console for more detailed info.'); console.log(error); } else { alert('Delete ' + file + ' successfully!'); refreshDirectoryFileList(); } }); } function createDirectory() { var fileService = getFileService(); if (!fileService) return; var directoryName = document.getElementById('newdirectory').value; fileService.createDirectoryIfNotExists(fileShare, currentPath.join('\\\\') + '\\' + directoryName, function(error, results) { if (error) { alert('Create directory failed, open browser console for more detailed info.'); console.log(error); } else { alert('Create ' + directoryName + ' successfully!'); refreshDirectoryFileList(); } }); } function displayProcess(process) { document.getElementById('progress').style.width = process + '%'; document.getElementById('progress').innerHTML = process + '%'; } function createFileFromStream(checkMD5) { var files = document.getElementById('files').files; if (!files.length) { alert('Please select a file!'); return; } var file = files[0]; var fileService = getFileService(); if (!fileService) return; var btn = document.getElementById("upload-button"); btn.disabled = true; btn.innerHTML = "Uploading"; var finishedOrError = false; var options = { contentSettings: { contentType: file.type }, storeFileContentMD5 : checkMD5 }; var speedSummary = fileService.createFileFromBrowserFile(fileShare, currentPath.join('\\\\'), file.name, file, options, function(error, result, response) { finishedOrError = true; btn.disabled = false; btn.innerHTML = "Upload"; if (error) { alert("Upload failed, open browser console for more detailed info."); console.log(error); displayProcess(0); } else { displayProcess(100); setTimeout(function() { // Prevent alert from stopping UI progress update alert('Upload successfully!'); }, 1000); refreshDirectoryFileList(); } }); speedSummary.on('progress', function () { var process = speedSummary.getCompletePercent(); displayProcess(process); }); } </script> </body> </html>