$(() => {
const loadPanel = $('#load-panel').dxLoadPanel({
position: { of: '#file-manager' },
}).dxLoadPanel('instance');
$.ajax({
url: 'https://js.devexpress.com/Demos/Mvc/api/file-manager-azure-status?widgetType=fileManager',
success(result) {
const className = result.active ? 'show-widget' : 'show-message';
$('#wrapper').addClass(className);
loadPanel.hide();
},
});
const endpointUrl = 'https://js.devexpress.com/Demos/Mvc/api/file-manager-azure-access';
gateway = new AzureGateway(endpointUrl, onRequestExecuted);
azure = new AzureFileSystem(gateway);
const provider = new DevExpress.fileManagement.CustomFileSystemProvider({
getItems,
createDirectory,
renameItem,
deleteItem,
copyItem,
moveItem,
uploadFileChunk,
downloadItems,
});
$('#file-manager').dxFileManager({
fileSystemProvider: provider,
allowedFileExtensions: [],
upload: {
maxFileSize: 1048576,
},
permissions: {
download: true,
// uncomment the code below to enable file/directory management
/* create: true,
copy: true,
move: true,
delete: true,
rename: true,
upload: true */
},
});
});
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) {
const 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) {
const 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) {
let deferred = null;
if (uploadInfo.chunkIndex === 0) {
const filePath = destinationDirectory.path ? `${destinationDirectory.path}/${fileData.name}` : fileData.name;
deferred = gateway.getUploadAccessUrl(filePath).done((accessUrl) => {
uploadInfo.customData.accessUrl = accessUrl;
});
} else {
deferred = $.Deferred().resolve().promise();
}
deferred = deferred.then(() => gateway.putBlock(
uploadInfo.customData.accessUrl,
uploadInfo.chunkIndex,
uploadInfo.chunkBlob,
));
if (uploadInfo.chunkIndex === uploadInfo.chunkCount - 1) {
deferred = deferred.then(() => 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),
);
}
let gateway = null;
let azure = null;
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>DevExtreme Demo</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script>window.jQuery || document.write(decodeURIComponent('%3Cscript src="js/jquery.min.js"%3E%3C/script%3E'))</script>
<script src="../azure-file-system.js"></script>
<link rel="stylesheet" type="text/css" href="https://cdn3.devexpress.com/jslib/22.2.3/css/dx.light.css" />
<script src="https://cdn3.devexpress.com/jslib/22.2.3/js/dx.all.js"></script>
<link rel="stylesheet" type="text/css" href="styles.css" />
<script src="data.js"></script>
<script src="index.js"></script>
</head>
<body class="dx-viewport">
<div class="demo-container">
<div id="wrapper">
<div id="widget-area">
<div id="file-manager"></div>
<div id="request-panel"></div>
</div>
<div id="load-panel"></div>
<div id="message-box">
To run the demo locally, specify your Azure storage account name, access key and container name in the web.config file. Refer to the
<a href="https://js.devexpress.com/Demos/WidgetsGallery/Demo/FileManager/AzureClientBinding/jQuery/Light/" target="_blank">
https://js.devexpress.com/Demos/WidgetsGallery/Demo/FileManager/AzureClientBinding/jQuery/Light/</a
>
to see the demo online.
</div>
</div>
</div>
</body>
</html>
#widget-area {
visibility: hidden;
}
#message-box {
display: none;
}
.show-widget #widget-area {
visibility: visible;
}
.show-message #widget-area {
display: none;
}
.show-message #message-box {
display: block;
}
#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;
}
using DevExtreme.MVC.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;
namespace DevExtreme.MVC.Demos.Controllers.ApiControllers {
public class FileManagerAzureAccessApiController : ApiController {
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.Value;
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.Value;
_container = Client.GetBlobContainerClient(accountModel.ContainerName);
}
return _container;
}
}
[HttpGet]
[Route("api/file-manager-azure-access", Name = "FileManagerAzureAccessApi")]
public HttpResponseMessage Process(string command, string blobName = null, string blobName2 = null) {
object result;
try {
result = ProcessCommand(command, blobName, blobName2);
} catch {
result = CreateErrorResult();
}
return Request.CreateResponse(result);
}
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
};
}
}
}