Your search did not match any results.

Azure Client-Side Binding

This demo illustrates how to use the custom file provider to connect the FileManager control to the Azure Blob Storage on the client side. The Custom File System Provider allows you to implement custom APIs to handle file operations (add, delete, rename, etc.). All APIs that implement access to Azure Blob Storage on the client are stored in the azure-file-system.js file. On the server, configure the Shared Access Signature (SAS) to grant access to blobs in the storage.

Backend API
@model DevExtreme.NETCore.Demos.Models.FileManagement.AzureStorageAccount @if(!Model.IsEmpty()) { @(Html.DevExtreme().FileManager() .ID("file-manager") .FileSystemProvider(provider => provider.Custom() .GetItems("getItems") .CreateDirectory("createDirectory") .RenameItem("renameItem") .DeleteItem("deleteItem") .CopyItem("copyItem") .MoveItem("moveItem") .UploadFileChunk("uploadFileChunk") .DownloadItems("downloadItems") ) .Permissions(permissions => { permissions.Download(true); // uncomment the code below to enable file/folder management // permissions.Create(true); // permissions.Copy(true); // permissions.Move(true); // permissions.Delete(true); // permissions.Rename(true); // permissions.Upload(true); }) .Upload(upload => upload.MaxFileSize(1048576)) .AllowedFileExtensions(new string[0]) ) <text> <div id="request-panel"></div> <script src="~/utils/azure-file-system.js"></script> <script> function getItems(parentDirectory) { return azure.getItems(parentDirectory.path); } function createDirectory(parentDirectory, name) { return azure.createDirectory(parentDirectory.path, name); } function renameItem(item, name) { return item.isDirectory ? azure.renameDirectory(item.path, name) : azure.renameFile(item.path, name); } function deleteItem(item) { return item.isDirectory ? azure.deleteDirectory(item.path) : azure.deleteFile(item.path); } function copyItem(item, destinationDirectory) { var destinationPath = destinationDirectory.path ? destinationDirectory.path + "/" + item.name : item.name; return item.isDirectory ? azure.copyDirectory(item.path, destinationPath) : azure.copyFile(item.path, destinationPath); } function moveItem(item, destinationDirectory) { var destinationPath = destinationDirectory.path ? destinationDirectory.path + "/" + item.name : item.name; return item.isDirectory ? azure.moveDirectory(item.path, destinationPath) : azure.moveFile(item.path, destinationPath); } function uploadFileChunk(fileData, uploadInfo, destinationDirectory) { var deferred = null; if(uploadInfo.chunkIndex === 0) { var filePath = destinationDirectory.path ? destinationDirectory.path + "/" + fileData.name : fileData.name; deferred = gateway.getUploadAccessUrl(filePath).done(function(accessUrl) { uploadInfo.customData.accessUrl = accessUrl; }); } else { deferred = $.Deferred().resolve().promise(); } deferred = deferred.then(function() { return gateway.putBlock(uploadInfo.customData.accessUrl, uploadInfo.chunkIndex, uploadInfo.chunkBlob); }); if(uploadInfo.chunkIndex === uploadInfo.chunkCount - 1) { deferred = deferred.then(function() { return gateway.putBlockList(uploadInfo.customData.accessUrl, uploadInfo.chunkCount); }); } return deferred.promise(); } function downloadItems(items) { azure.downloadFile(items[0].path); } function onRequestExecuted(e) { $("<div>").addClass("request-info").append( createParameterInfoDiv("Method:", e.method), createParameterInfoDiv("Url path:", e.urlPath), createParameterInfoDiv("Query string:", e.queryString), $("<br>") ) .prependTo("#request-panel"); } function createParameterInfoDiv(name, value) { return $("<div>").addClass("parameter-info").append( $("<div>").addClass("parameter-name").text(name), $("<div>").addClass("parameter-value dx-theme-accent-as-text-color").text(value).attr("title", value) ); } var endpointUrl = '@Url.RouteUrl("FileManagerAzureAccessApi")'; var gateway = new AzureGateway(endpointUrl, onRequestExecuted); var azure = new AzureFileSystem(gateway); </script> </text> } else { <text> To run the demo locally, specify your Azure storage account name, access key and container name in the appsettings.json file. Refer to the <a href="https://demos.devexpress.com/ASPNetCore/Demo/FileManager/AzureClientBinding/" target="_blank"> https://demos.devexpress.com/ASPNetCore/Demo/FileManager/AzureClientBinding/ </a> to see the demo online. </text> }
using DevExtreme.NETCore.Demos.Models.FileManagement; using Microsoft.AspNetCore.Mvc; namespace DevExtreme.NETCore.Demos.Controllers { public class FileManagerController : Controller { public IActionResult AzureClientBinding() { return View(AzureStorageAccount.FileManager); } } }
using DevExtreme.NETCore.Demos.Models.FileManagement; using System; using System.Net.Http; using System.Web.Http; using Azure.Storage; using Azure.Storage.Sas; using Azure.Storage.Blobs; using Azure.Storage.Blobs.Models; using Azure.Storage.Blobs.Specialized; using Microsoft.AspNetCore.Mvc; namespace DevExtreme.NETCore.Demos.Controllers { public class FileManagerAzureAccessApiController : Controller { const string EmptyDirDummyBlobName = "aspxAzureEmptyFolderBlob"; const string ServiceUri = "https://{0}.blob.core.windows.net"; const long MaxBlobSize = 1048576; public FileManagerAzureAccessApiController() { AllowDownload = true; //uncomment the code below to enable file/folder management //AllowCreate = true; //AllowRemove = true; //AllowRenameOrMoveOrCopy = true; //AllowUpload = true; } bool AllowCreate { get; } bool AllowRemove { get; } bool AllowRenameOrMoveOrCopy { get; } bool AllowUpload { get; } bool AllowDownload { get; } BlobServiceClient _client; BlobServiceClient Client { get { if(_client == null) { AzureStorageAccount accountModel = AzureStorageAccount.FileManager; StorageSharedKeyCredential credential = new StorageSharedKeyCredential(accountModel.AccountName, accountModel.AccessKey); _client = new BlobServiceClient(new Uri(string.Format(ServiceUri, accountModel.AccountName)), credential); } return _client; } } BlobContainerClient _container; BlobContainerClient Container { get { if(_container == null) { AzureStorageAccount accountModel = AzureStorageAccount.FileManager; _container = Client.GetBlobContainerClient(accountModel.ContainerName); } return _container; } } [Route("api/file-manager-azure-access", Name = "FileManagerAzureAccessApi")] public object Process(string command, string blobName = null, string blobName2 = null) { try { return ProcessCommand(command, blobName, blobName2); } catch { return CreateErrorResult(); } } object ProcessCommand(string command, string blobName, string blobName2) { switch(command) { case "BlobList": return GetBlobList(); case "CreateDirectory": if(!AllowCreate) return CreateErrorResult(); return CreateDirectory(blobName); case "DeleteBlob": if(!AllowRemove) return CreateErrorResult(); return DeleteBlob(blobName); case "CopyBlob": if(!AllowRenameOrMoveOrCopy) return CreateErrorResult(); return CopyBlob(blobName, blobName2); case "UploadBlob": if(!AllowUpload) return CreateErrorResult(); return UploadBlob(blobName); case "GetBlob": if(!AllowDownload) return CreateErrorResult(); return GetBlob(blobName); } return null; } object GetBlobList() { if(Container.CanGenerateSasUri) { var sasUri = Container.GenerateSasUri(BlobContainerSasPermissions.List, DateTimeOffset.UtcNow.AddHours(1)); return CreateSuccessResult(sasUri); } else { return CreateErrorResult("BlobContainerClient cannot generate SasUri"); } } object CreateDirectory(string directoryName) { string blobName = $"{directoryName}/{EmptyDirDummyBlobName}"; var blob = Container.GetBlobClient(blobName); if(blob.Exists()) { return CreateErrorResult(); } var sasUri = TryGetBlobUri(blob, BlobSasPermissions.Write); if(sasUri != null) { return CreateSuccessResult(sasUri); } else { return CreateErrorResult("BlobClient cannot generate SasUri"); } } object DeleteBlob(string blobName) { var sasUri = TryGetBlobUri(blobName, BlobSasPermissions.Delete); if(sasUri != null) { return CreateSuccessResult(sasUri); } else { return CreateErrorResult("BlobClient cannot generate SasUri"); } } object CopyBlob(string sourceBlobName, string destinationBlobName) { var sourceSasUri = TryGetBlobUri(sourceBlobName, BlobSasPermissions.Read); var destinationSasUri = TryGetBlobUri(destinationBlobName, BlobSasPermissions.Create); if(sourceSasUri != null && destinationSasUri != null) { return CreateSuccessResult(sourceSasUri, destinationSasUri); } else { return CreateErrorResult("BlobClient cannot generate SasUri"); } } object UploadBlob(string blobName) { if(blobName.EndsWith("/")) return CreateErrorResult("Invalid blob name."); var blob = Container.GetBlockBlobClient(blobName); if(blob.Exists() && blob.GetProperties().Value.ContentLength > MaxBlobSize) { return CreateErrorResult(); } var sasUri = TryGetBlobUri(blobName, BlobSasPermissions.Write); return CreateSuccessResult(sasUri); } object GetBlob(string blobName) { var headers = new BlobHttpHeaders { ContentType = "application/octet-stream" }; var blob = Container.GetBlobClient(blobName); blob.SetHttpHeaders(headers); var sasUri = TryGetBlobUri(blob, BlobSasPermissions.Read); return CreateSuccessResult(sasUri); } Uri TryGetBlobUri(string blobName, BlobSasPermissions permissions) { if(!string.IsNullOrEmpty(blobName)) { return TryGetBlobUri(Container.GetBlobClient(blobName), permissions); } else { return null; } } Uri TryGetBlobUri(BlobClient blob, BlobSasPermissions permissions) { if(blob.CanGenerateSasUri) { return blob.GenerateSasUri(permissions, DateTimeOffset.UtcNow.AddHours(1)); } else { return null; } } object CreateSuccessResult(Uri uri, Uri uri2 = null) { return new { success = true, accessUrl = uri.AbsoluteUri, accessUrl2 = uri2 != null ? uri2.AbsoluteUri : null }; } object CreateErrorResult(string error = null) { if(string.IsNullOrEmpty(error)) error = "Unspecified error."; return new { success = false, error = error }; } } }
#request-panel { min-width: 505px; height: 400px; overflow-x: hidden; overflow-y: auto; padding: 18px; margin-top: 40px; background-color: rgba(191, 191, 191, 0.15); } #request-panel .parameter-info { display: flex; } .request-info .parameter-name { flex: 0 0 100px; } .request-info .parameter-name, .request-info .parameter-value { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }