Giter Site home page Giter Site logo

trannamtrung1st / elfinder.net.core Goto Github PK

View Code? Open in Web Editor NEW
11.0 1.0 6.0 218 KB

An elFinder backend connector with less magic code and more compatibility. This enables .NET Standard 2.0 projects to easily integrate elFinder functionalities.

License: Apache License 2.0

C# 94.29% HTML 5.04% CSS 0.57% JavaScript 0.10%
filemanager filemanager-ui elfinder

elfinder.net.core's Introduction

elFinder.Net.Core

Logo

Getting Started

  1. Install the NuGet package: https://www.nuget.org/packages/elFinder.Net.Core/
  2. Look at the basic demo project for an example of how to integrate it into your web project. (the example uses ASP.NET Core 3.1 and some additional packages listed below).

Advanced

The advanced demo project has some additional use cases enabled, including:

  • Integrate Authentication/Authorization (Cookies, OAuth2 JWT).
  • Multi-tenant support.
  • Events.
  • Some customized behaviors can be done outside the core library.
  • Integrate Quota management plugin.
  • For an example of how to write a plugin, see Logging plugin example. This plugin intercepts all method calls of IConnector and IDriver instances then logs the method's information (arguments, method name, return value, .etc) to the console output.

Customization

Since file management is a complex topic and the requirements are diverse, here are some ways to customize the library:

  1. Override the default implementation
  2. Use interceptors (as those plugins here which use Castle DynamicProxy and built-in .NET Core DI container).

Some important classes and their descriptions:

  • IConnector/Connector: the backend connector which handles elFinder commands sent from clients.
  • IDriver/FileSystemDriver: the driver which provides a storage mechanism (in this case, the OS file system). There are other drivers for different storage, e.g, elFinder AzureStorage.
  • IFile/FileSystemFile; IDirectory/FileSystemDirectory: the file system's abstractions/implementations.
  • Others: please download the repository, then run the demo projects. They should walk through all of the important classes.

About this repository

There are 3 main projects:

  • elFinder.Net.Core: the core backend connector for elFinder.
  • elFinder.Net.AspNetCore: enable ASP.NET Core 2.2 projects to easily integrate the connector package.
  • elFinder.Net.Drivers.FileSystem: the default Local File System driver.

Plugins:

  • Plugins/elFinder.Net.Plugins.FileSystemQuotaManagement: enable quota management and restriction features.

Credits

elFinder.Net.Core is based on the project elFinder.NetCore of Matt Gordon. Many thanks for the excellent works. For those who may get confused about which package to use, try and find the one that best suits your project. I create this with some modification that suits my use cases. Some of the main differences are:

  • Enable better security, ACL (for both Frontend and Backend)
  • Support .NET Standard 2.0 (remove ASP.NET Core dependency).
  • Customizable through models, interfaces, and events.
  • More features and extensibility: plugins, interceptors, etc.
  • Support more commands.
  • Follow the specification from https://github.com/Studio-42/elFinder/wiki more strictly.

elfinder.net.core's People

Contributors

dependabot[bot] avatar trannamtrung1st avatar trung-tran-sts avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

elfinder.net.core's Issues

Upload multiple files to multiple target folder

Hi, in this project I can customize target folder uploaded files by overwrite the IFormFileWrapper #30 like this

var overrideForm = new Dictionary<string, StringValues>(cmd.Form);
var ext = await _fileExtensionRepository.FindByExt(type);
overrideForm["target"] = $"{ext.FolderId}~{ext.Type}_";
cmd.Form = overrideForm;

Now I need to upload multiple files with each file having a different target folder. Is it possible to upload multiple files to multiple target folder?

Block drag and drop for locked files

Hi There, I'd like to be able to block drag and drop of files in locked folders, but allow it in unlocked folders. Oddly, the way to make ElFinder JS do this is to disable the copy, cut and paste commands on the server side.

This change can be wrought by adding code like this to the constructor or ConnectorResponseOptions.cs:
if (directory.ObjectAttribute.Locked) { this.disabled.AddRange(new string[] {ConnectorCommand.Ui_copy, ConnectorCommand.Ui_cut, ConnectorCommand.Ui_paste}); }

While this suits my use case, I appreciate others might want to be able to drag files that are in a locked directory. We could make "Draggable" an option in the ObjectAttribute, or perhaps you can think of a more elegant solution? Please let me know your thoughts? Thanks.

Save Data to Database using Dependency Injection & EF

Hi, I have problem when try to save data to database using dependency injection & EF in the event, this is my code

_driver.OnAfterUpload += async (sender, args) => { Console.WriteLine($"Uploaded to: {args.File.FullName}"); await _fileRepository.Create(new() { FullName = args.File.FullName }); };

So, is it possible to save data like this or there is another way?

MaxUploadConnections is not respected when you drill into a folder

To see the issue, set MaxUploadConnections to some value other than 1 when creating the volumes.

On the initial api request to connector (cmd = open & init=1) we can see that the correct uploadMaxConn appears in the JSON.

Drill into a folder in elfinder and again look at the call to connector cmd=open call that occurred when you went into the folder. We see that uploadMaxConn is always set to 1.

I noticed this when experimenting with MaxUploadConnections =-1 to disable file upload chunking.

There's a line in FileSystemDriver.cs:
initResp.options.uploadMaxConn = currentVolume.MaxUploadConnections;
Which is involved when init =1, but not otherwise.

Async Event handlers are not awaited

I would like to use an async event handler for things like OnAfterUpload (e.g. to do a database query and send an email). The only way to do that is with an async void return type on the event handler. This means the caller can't await the result, so the rest of the API request finishes and all the associated dependencies (database context, etc) are disposed. It's random as to which order the dispose and event handler run in, leading to difficult to diagnose bugs.

Reading around, there doesn't seem to be a great story for EventHandler with async methods. I wonder if it would be better to allow delegates to be passed to ElFinder.Net.Core and invoke them with an await? This is not so much of a bug report, as a "can you think of a way this can work better?" question.

Here are a couple of articles I came across:
https://medium.com/@a.lyskawa/the-hitchhiker-guide-to-asynchronous-events-in-c-e9840109fb53

Balanced with:
https://docs.microsoft.com/en-us/archive/msdn-magazine/2013/march/async-await-best-practices-in-asynchronous-programming#avoid-async-void

I'd be interested to know your thoughts?

Thanks.

Strange behavior when set Volume Id

Hi, when I want to set volume Id in SetupConnectorAsync() I can't select multiple files using mouse click range or using shift key, I can still select all by using ctrl + a. Why is that? Is it can be fixed? Thank you

// Volume initialization
 var volume = new Volume(_driver,
                Startup.MapStoragePath($"./upload/{volumePath}"),
                Startup.TempPath,
                $"/api/files/storage/upload/{volumePath}/",
                $"/api/files/thumb/",
                thumbnailDirectory: Startup.MapStoragePath($"./thumb/{volumePath}"))
            {
                Name = "My volume",
                MaxUploadFiles = 20,
                MaxUploadSizeInMb = 10,
                MaxUploadConnections = 3, // 3 upload requests at a time
                //UploadAllow = new[] { "text" },
                UploadDeny = new[] { "image", "text/csv" },
                UploadOrder = new[] { UploadConstraintType.Allow, UploadConstraintType.Deny },

                VolumeId = userId + "~" + userId + "_", // set volume id
            };

Download single file

Hi,

Your new updated feature "zipdl" are awesome, but I think there is issue when download a single file.. there is a process that never ends even though download file is complete. Can you fix this? Thank you

Screen Shot 2021-06-17 at 6 05 36 PM

Thumbnails for video

Hi,

Thumbnail image in this project work fine and I'm trying to generate thumbnail for video too. I already create API for generate image from video using ffmpeg but it seem only file image that can be process for thumbnail in this project. So, is it possible to generate thumbnail for video? thanks

Delete Thumbnail

Hi,

I have issue when delete image file with its thumbnail. The thumbnail not deleted because it has different generate thumbname when process delete. I think thats because the original image file already deleted when trying to generate thumbname so the file.LastWriteTimeUtcAsync is zero.. I tried to move method RemoveThumbsAsync before DeleteAsync and it works. So is there any reason to delete file first before delete thumbnail or better delete thumbnail first before delete image file?

Add Trash Volume

Hi, This project is excellent. I think it will be great if trash volume function added in this project

Event needed after all files are uploaded

I've been using the OnAfterUpload event to send a notification email each time a file is uploaded, but if the user selects 30 files to upload in one go, then this generates far too many emails. It'd be better to send a single email with a list of all the files that were uploaded. Please would it be possible to add an event after all files have been uploaded? Something like this around line 954 of FileSystemDriver.cs:

await OnAfterAllFilesUploaded.SafeInvokeAsync( array of files, array of destFiles, etc);

Thanks!

Save data to the database

Hi,

Is it possible to save files/folders in FileSystem driver normally and at the same time use database to save files/folders information?

Right now I'm using conResult.Response in the FilesController to store the data to database, but I have difficult time with rename and cut folder because conResult.Response does not grab information files/subfolders inside the folder.
So, is there a better ways to store data to the database? Thank you

Modify uploaded file name

Hi, is it possible to customize upload form to add text field and then change uploaded file name based on input text field?

Javascript warnings "The volume root statuses requires `volumeid` property"

When running the demos, if I open the debugging console in the web browser I see lots of javascript warnings saying:
"The volume root statuses requires volumeid property"

This is because the current working directory (CWD) property doesn't have a volumeid property.
The fix for this would be to change the return type of IDirectoryExtensions -> ToFileInfoAsync to be Task DirectoryInfoResponse instead of Task BaseInfoResponse
You'll also want to change the first parameter of InitResponse's and OpenResponse's constructors to be "DirectoryInfoResponse cwd" instead of "BaseInfoResponse cwd".
Finally change the cwd property in OpenResponse to be:
public DirectoryInfoResponse cwd { get; protected set; }

Thanks!

Prevent direct access to files from URL

Hi,

In your demo project I noticed that user cant access files from url, thats good. I try to create new project with blazor wasm and using this library but cant prevent direct access to files from URL. So, is there any configuration to prevent direct access to files from URL?

Customize status bar text

Hi,

The quota management feature in this project is cool, btw is it possible to customize status bar text to show something like:
"Maximum: 10.00 MB, Usage: 6.00 MB, 4.00 MB still available" and update that text after each operation?

Download file with authorization

Hi,

I have a problem when download file. I'm using Blazor and web token authentication using customHeaders. The problem is that I cant download any file from Elfinder.

The browser says, "Failed - Needs authorization."
I don't get any errors in the browser console nor network tab.
I tested the API with Postman (and web token), and everything is fine.

I think customHeaders are not included when I try to download from elfinder, have you any idea to solve this problem?
Thank you

All volume files and folders to be readonly and locked, except for uploads folder

Hi there, I'd all files and folders in a volume to be locked and readonly, EXCEPT for a special "uploads" folder in each volume. I don't think it's currently possible to configure it that way? The root volume folder can only be set to locked & readonly by setting volume.IsLocked = true, volume.IsReadOnly = true. These setting override any ObjectAttributes I set for child folders due to code like this in IDirectoryExtensions and IFileExtensions:

objAttr.Write = volume.IsReadOnly ? false : objAttr.Write;
objAttr.Locked = volume.IsLocked ? true : objAttr.Locked;
objAttr.ShowOnly = volume.IsShowOnly ? true : objAttr.ShowOnly;

Would it be worth adding an additional property to Volume to specify that volume.IsReadOnly, etc, only applies to the root folder and not to child folders? Another approach would be to allow ObjectAttributes to trump volume settings, but that might break the contract for existing users.

PS - Thanks for your excellent work on this project - it's a lot better designed than the original elFinder.NetCore.

Storage usage not updated when using custom FileSystemDriver

Hi, I have issue when using custom FileSystemDriver. Storage usage not updated after upload or delete file, it seems GetPhysicalStorageUsageAsync not executed when using custom FileSystemDriver eventhough I'm not override any method in FileSystemDriver yet. Here is my code :

In Startup.cs

public void ConfigureServices(IServiceCollection services){
            //
            var pluginCollection = new PluginCollection();

            services.AddElFinderAspNetCore()
                 .AddApplicationFileSystemDriver(tempFileCleanerConfig: (opt) =>
                 {
                     opt.ScanFolders.Add(TempPath, TempFileCleanerOptions.DefaultUnmanagedLifeTime);
                 })
                .AddFileSystemQuotaManagement(pluginCollection)
                .AddElFinderPlugins(pluginCollection);
            //
}

Add new ApplicationServiceCollectionExtensions.cs

public static class ApplicationServiceCollectionExtensions
    {
        public static IServiceCollection AddApplicationFileSystemDriver(this IServiceCollection services,
            Action<TempFileCleanerOptions> tempFileCleanerConfig = null)
        {
            if (tempFileCleanerConfig == null)
                tempFileCleanerConfig = (opt) => { };

            return services.AddScoped<IDriver, ApplicationFileSystemDriver>()
                .AddSingleton<IZipDownloadPathProvider, TempZipDownloadPathProvider>()
                .AddSingleton<IZipFileArchiver, ZipFileArchiver>()
                .AddSingleton<IThumbnailBackgroundGenerator, DefaultThumbnailBackgroundGenerator>()
                .AddSingleton<ICryptographyProvider, DefaultCryptographyProvider>()
                .AddSingleton<ITempFileCleaner, DefaultTempFileCleaner>()
                .Configure(tempFileCleanerConfig);
        }
    }

Add new ApplicationFileSystemDriver.cs

public class ApplicationFileSystemDriver : FileSystemDriver
    {
        public ApplicationFileSystemDriver(IPathParser pathParser,
            IPictureEditor pictureEditor,
            IVideoEditor videoEditor,
            IZipDownloadPathProvider zipDownloadPathProvider,
            IZipFileArchiver zipFileArchiver,
            IThumbnailBackgroundGenerator thumbnailBackgroundGenerator,
            ICryptographyProvider cryptographyProvider,
            IConnector connector,
            IConnectorManager connectorManager,
            ITempFileCleaner tempFileCleaner) : base(pathParser, pictureEditor, videoEditor, zipDownloadPathProvider, zipFileArchiver, thumbnailBackgroundGenerator, cryptographyProvider, connector, connectorManager, tempFileCleaner)
        {
        }

    }

And this is my repo https://github.com/benny-adiwijaya/ElFinderWeb31.git

Do you have any clue why storage usage not updated or GetPhysicalStorageUsageAsync not executed after upload or remove file? Thank you

Customize upload progress bar

Hi,

Uploading large file in this project works fine. Anyway, is it possible to customize upload progress bar by adding something like percentage, speed transfer, and time estimation for better user experience?

Customize path for preview non regular video file

Hi, is there a way to customize path for preview non regular video file so the preview is not play the original file?

I can do it with regular video file like mp4 by simply change path in GetFile action. But with non regular video file like AVI or MXF need extra work.

this.support = {
			audio: {
				ogg: support('audio/ogg;'),
				webm: support('audio/webm;'),
				mp3: support('audio/mpeg;'),
				wav: support('audio/wav;'),
				m4a: support('audio/mp4;') || support('audio/x-m4a;') || support('audio/aac;'),
				flac: support('audio/flac;'),
				amr: support('audio/amr;')
			},
			video: {
				ogg: support('video/ogg;'),
				webm: support('video/webm;'),
				mp4: support('video/mp4;'),
				avi: support('video/mp4;'), // added
				mxf: support('video/mp4;'),
				mkv: support('video/x-matroska;') || support('video/webm;'),
				'3gp': support('video/3gpp;') || support('video/mp4;'), // try as mp4
				m3u8: support('application/x-mpegURL', 'video') || support('application/vnd.apple.mpegURL', 'video'),
				mpd: support('application/dash+xml', 'video')
			}
		};
mimes = {
					'video/mp4': 'mp4',
					'video/mp4': 'avi',
					'video/mp4': 'mxf',
					'video/x-m4v': 'mp4',
					'video/quicktime': 'mp4',
					'video/mpeg': 'mpeg',
					'video/ogg': 'ogg',
					'application/ogg': 'ogg',
					'video/webm': 'webm',
					'video/x-matroska': 'mkv',
					'video/3gpp': '3gp',
					'application/vnd.apple.mpegurl': 'm3u8',
					'application/x-mpegurl': 'm3u8',
					'application/dash+xml': 'mpd',
					'video/x-flv': 'flv',
					'video/x-msvideo': 'avi',
					'application/mxf': 'mxf'
				},

By adding avi: support('video/mp4;'), and 'video/mp4': 'avi', somehow it works with AVI file, but it dont work with MXF files as it wont open video preview.

PS. The new path I use is mp4 file so it can be played with browser

Inconsistent Volume order

Sorry - another minor bug + suggested fix. In the demos, highlight Volume 2. Press refresh. The volumes are listed as:
Volume 2
Volume 0
Volume 1
Volume 3
Volume 4
Go into a subfolder under Volume 2 and press refresh. The volumes are listed as:
Volume 0
Volume 1
Volume 2
-> Subfolder
Volume 3
Volume 4

The simplest fix would be to add an OrderBy on line 169 of Connector.cs:
openResp.files = openResp.files.OrderBy(f => (f as BaseInfoResponse)?.name ?? string.Empty).ToList();
And make the files property setter public. There may be a more elegant place to put this with a bit of refactoring.
Thanks.

Empty the folder

When I try command "empty the folder", the folder I selected get deleted too

Customize Error Message

Hi, in this project when user open application for the first time they got error message "Unable to connect to backend.
HTTP error 401". Is there a way to customize the error message so it can become more user friendly?

Searching file not working

Hi,

I think searching file is not really working, I just type the name of file in the search form and press enter but the result is empty eventhough the file is exist

Customize uploadingFileName

Hi, is it posible to customize uploadingFileName without overriding UploadAsync, so the server can control file name that uploaded by user?

Event doesn't work when override uploadAsync

Hi,

I have issue when override uploadAsync, it seem doesnt trigger the event _driver.OnAfterUpload or _driver.OnAfterChunkMerged in FilesControlles eventhough I dont make any modification when override uploadAsync

Update usage

Hi,

Is it possible to update usage in every action like copy, upload, delete etc instead only when open directory? I already tried to do so but sometimes the usage value is not correct and won't change except when open directory

Create Custom FileSystemDirectory

Hi, I need to create custom FileSystemDirectory. I already create new class that inherits from FileSystemDirectory

public class ApplicationFileSystemDirectory : FileSystemDirectory
	{
        public ApplicationFileSystemDirectory(string dirName, IVolume volume) : base(dirName, volume)
        {
        }

        public override Task<IEnumerable<IFile>> GetFilesAsync(string search, bool verify = true,
            Func<IFile, bool> filter = null, SearchOption searchOption = default, CancellationToken cancellationToken = default)
        {
            cancellationToken.ThrowIfCancellationRequested();

            if (search == null) throw new ArgumentNullException(nameof(search));

            if (verify && !ObjectAttribute.Read) return Task.FromResult<IEnumerable<IFile>>(new IFile[0]);

            if (!search.Contains('*'))
                search = '*' + search + '*';

            var files = directoryInfo.EnumerateFiles(search, searchOption).Select(f => new FileSystemFile(f, volume) as IFile);

            if (filter != null) files = files.Where(filter);
            else files = files.Where(file => file.ObjectAttribute.Visible);

            return Task.FromResult(files);
        }
    }

How to register custom FileSystemDirectory class in program.cs / StartUp.cs?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.