trannamtrung1st / elFinder.Net.Core

An elFinder backend connector with less magic code and more compatibility. This enables .NET Standard 2.0 projects to easily integrate elFinder functionalities.
Apache License 2.0
12 stars 8 forks source link

Event doesn't work when override uploadAsync #28

Closed benny-adiwijaya closed 2 years ago

benny-adiwijaya commented 2 years ago

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

trannamtrung1st commented 2 years ago

Strange. Can you show me your overriding code of the UploadAsync method?

benny-adiwijaya commented 2 years ago

Hi @trannamtrung1st

This is my code

public class ApplicationNewFileSystemDriver : FileSystemDriver
    {
        public const string ChunkingFolderPrefix = "_uploading_";
        public const string DefaultThumbExt = ".png";
        private static readonly char[] InvalidFileNameChars = Path.GetInvalidFileNameChars();

        protected readonly IPathParser _pathParser;
        protected readonly IPictureEditor _pictureEditor;
        protected readonly IVideoEditor _videoEditor;
        protected readonly IZipDownloadPathProvider _zipDownloadPathProvider;
        protected readonly IZipFileArchiver _zipFileArchiver;
        protected readonly IThumbnailBackgroundGenerator _thumbnailBackgroundGenerator;
        protected readonly IConnector _connector;
        protected readonly IConnectorManager _connectorManager;
        protected readonly ICryptographyProvider _cryptographyProvider;
        protected readonly ITempFileCleaner _tempFileCleaner;

        public event BeforeRemoveThumbAsync OnBeforeRemoveThumb;
        public event AfterRemoveThumbAsync OnAfterRemoveThumb;
        public event RemoveThumbErrorAsync OnRemoveThumbError;
        public event BeforeMakeDirAsync OnBeforeMakeDir;
        public event AfterMakeDirAsync OnAfterMakeDir;
        public event BeforeMakeFileAsync OnBeforeMakeFile;
        public event AfterMakeFileAsync OnAfterMakeFile;
        public event BeforeRenameAsync OnBeforeRename;
        public event AfterRenameAsync OnAfterRename;
        public event BeforeRemoveAsync OnBeforeRemove;
        public event AfterRemoveAsync OnAfterRemove;
        public event BeforeRollbackChunkAsync OnBeforeRollbackChunk;
        public event AfterRollbackChunkAsync OnAfterRollbackChunk;
        public event BeforeUploadAsync OnBeforeUpload;
        public event AfterUploadAsync OnAfterUpload;
        public event BeforeChunkMergedAsync OnBeforeChunkMerged;
        public event AfterChunkMergedAsync OnAfterChunkMerged;
        public event BeforeChunkTransferAsync OnBeforeChunkTransfer;
        public event AfterChunkTransferAsync OnAfterChunkTransfer;
        public event UploadErrorAsync OnUploadError;
        public event BeforeMoveAsync OnBeforeMove;
        public event AfterMoveAsync OnAfterMove;
        public event BeforeCopyAsync OnBeforeCopy;
        public event AfterCopyAsync OnAfterCopy;
        public event BeforeArchiveAsync OnBeforeArchive;
        public event AfterArchiveAsync OnAfterArchive;
        public event ArchiveErrorAsync OnArchiveError;
        public event BeforeExtractAsync OnBeforeExtract;
        public event AfterExtractAsync OnAfterExtract;
        public event BeforeExtractFileAsync OnBeforeExtractFile;
        public event AfterExtractFileAsync OnAfterExtractFile;
        public event BeforeWriteDataAsync OnBeforeWriteData;
        public event AfterWriteDataAsync OnAfterWriteData;
        public event BeforeWriteStreamAsync OnBeforeWriteStream;
        public event AfterWriteStreamAsync OnAfterWriteStream;
        public event BeforeWriteContentAsync OnBeforeWriteContent;
        public event AfterWriteContentAsync OnAfterWriteContent;

        public ApplicationNewFileSystemDriver(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)
        {
            _pathParser = pathParser;
            _pictureEditor = pictureEditor;
            _videoEditor = videoEditor;
            _zipDownloadPathProvider = zipDownloadPathProvider;
            _zipFileArchiver = zipFileArchiver;
            _thumbnailBackgroundGenerator = thumbnailBackgroundGenerator;
            _connector = connector;
            _connectorManager = connectorManager;
            _cryptographyProvider = cryptographyProvider;
            _tempFileCleaner = tempFileCleaner;
        }

        public override async Task<UploadResponse> UploadAsync(UploadCommand cmd, CancellationToken cancellationToken = default)
        {
            cancellationToken.ThrowIfCancellationRequested();

            if (cmd.Name.Any(name => !IsObjectNameValid(name)))
                throw new InvalidFileNameException();

            if (cmd.Renames.Any(name => !IsObjectNameValid(name)))
                throw new InvalidFileNameException();

            if (!IsObjectNameValid(cmd.Suffix) || !IsObjectNameValid(cmd.UploadName))
                throw new InvalidFileNameException();

            var isChunking = cmd.Chunk.ToString().Length > 0;
            var isChunkMerge = isChunking && cmd.Cid.ToString().Length == 0;
            var isFinalUploading = !isChunking || isChunkMerge;

            if (isChunking && (cmd.Chunk.Any(name => !IsObjectNameValid(name))))
                throw new InvalidFileNameException();

            if (!isFinalUploading && !IsObjectNameValid(cmd.ChunkInfo.UploadingFileName))
                throw new InvalidFileNameException();

            var uploadResp = new UploadResponse();
            var targetPath = cmd.TargetPath;
            var volume = targetPath.Volume;
            var warning = uploadResp.GetWarnings();
            var warningDetails = uploadResp.GetWarningDetails();
            var setNewParents = new HashSet<IDirectory>();

            if (isFinalUploading)
            {
                foreach (var uploadPath in cmd.UploadPathInfos.Distinct())
                {
                    var directory = uploadPath.Directory;
                    string lastParentHash = null;

                    while (!volume.IsRoot(directory))
                    {
                        var hash = lastParentHash ?? directory.GetHash(volume, pathParser);
                        lastParentHash = directory.GetParentHash(volume, pathParser);

                        if (!await directory.ExistsAsync && setNewParents.Add(directory))
                            uploadResp.added.Add(await directory.ToFileInfoAsync(hash, lastParentHash, volume, connector.Options, cancellationToken: cancellationToken));

                        directory = directory.Parent;
                    }
                }
            }

            if (isChunkMerge)
            {
                FileSystemDirectory chunkingDir = null;
                FileSystemFile uploadFileInfo = null;

                try
                {
                    string uploadingFileName = Path.GetFileName(cmd.UploadName);
                    string chunkMergeName = Path.GetFileName(cmd.Chunk);

                    var uploadDir = cmd.UploadPath.Count > 0 ? cmd.UploadPathInfos.Single().Directory : cmd.TargetPath.Directory;
                    var uploadDirHash = cmd.UploadPath.Count > 0 ? cmd.UploadPath.Single() : cmd.Target;
                    var chunkingDirFullName = PathHelper.SafelyCombine(uploadDir.Volume.ChunkDirectory,
                        uploadDir.Volume.ChunkDirectory, chunkMergeName);
                    chunkingDir = new FileSystemDirectory(chunkingDirFullName, volume);

                    if (!await chunkingDir.ExistsAsync)
                        throw new DirectoryNotFoundException();

                    if (!uploadDir.CanCreateObject())
                        throw new PermissionDeniedException($"Permission denied: {volume.GetRelativePath(uploadDir)}");

                    var uploadFullName = PathHelper.SafelyCombine(uploadDir.FullName, uploadDir.FullName, uploadingFileName);
                    uploadFileInfo = new FileSystemFile(uploadFullName, volume);
                    var isOverwrite = false;

                    if (await uploadFileInfo.ExistsAsync)
                    {
                        if (cmd.Renames.Contains(uploadingFileName))
                        {
                            var fileNameWithoutExt = Path.GetFileNameWithoutExtension(uploadingFileName);
                            var ext = Path.GetExtension(uploadingFileName);
                            var backupName = $"{fileNameWithoutExt}{cmd.Suffix}{ext}";
                            var fullBakName = PathHelper.SafelyCombine(uploadFileInfo.Parent.FullName, uploadFileInfo.Parent.FullName, backupName);
                            var bakFile = new FileSystemFile(fullBakName, volume);

                            if (await bakFile.ExistsAsync)
                                backupName = await bakFile.GetCopyNameAsync(cmd.Suffix, cancellationToken: cancellationToken);

                            var prevName = uploadFileInfo.Name;
                            await OnBeforeRename.SafeInvokeAsync(uploadFileInfo, backupName);
                            await uploadFileInfo.RenameAsync(backupName, cancellationToken: cancellationToken);
                            await OnAfterRename.SafeInvokeAsync(uploadFileInfo, prevName);

                            uploadResp.added.Add(await uploadFileInfo.ToFileInfoAsync(uploadDirHash, volume, pathParser, pictureEditor, videoEditor, cancellationToken: cancellationToken));
                            uploadFileInfo = new FileSystemFile(uploadFullName, volume);
                        }
                        else if (cmd.Overwrite == 0 || (cmd.Overwrite == null && !volume.UploadOverwrite))
                        {
                            string newName = await uploadFileInfo.GetCopyNameAsync(cmd.Suffix, cancellationToken: cancellationToken);
                            uploadFullName = PathHelper.SafelyCombine(uploadFileInfo.DirectoryName, uploadFileInfo.DirectoryName, newName);
                            uploadFileInfo = new FileSystemFile(uploadFullName, volume);
                            isOverwrite = false;
                        }
                        else if (!uploadFileInfo.ObjectAttribute.Write)
                            throw new PermissionDeniedException();
                        else isOverwrite = true;
                    }

                    var chunkedUploadInfo = connectorManager.GetLock<ChunkedUploadInfo>(chunkingDir.FullName);

                    if (chunkedUploadInfo == null)
                        throw new ConnectionAbortedException();

                    await OnBeforeChunkMerged.SafeInvokeAsync(uploadFileInfo, isOverwrite);
                    chunkedUploadInfo.IsFileTouched = true;
                    await MergeChunksAsync(uploadFileInfo, chunkingDir, isOverwrite, cancellationToken: cancellationToken);
                    await OnAfterChunkMerged.SafeInvokeAsync(uploadFileInfo, isOverwrite);

                    connectorManager.ReleaseLockCache(chunkingDir.FullName);

                    await uploadFileInfo.RefreshAsync(cancellationToken);
                    uploadResp.added.Add(await uploadFileInfo.ToFileInfoAsync(uploadDirHash, volume, pathParser, pictureEditor, videoEditor, cancellationToken: cancellationToken));
                }
                catch (Exception ex)
                {
                    var chunkedUploadInfo = connectorManager.GetLock<ChunkedUploadInfo>(chunkingDir.FullName);

                    if (chunkedUploadInfo != null)
                    {
                        lock (chunkedUploadInfo)
                        {
                            chunkedUploadInfo.Exception = ex.GetRootCause();

                            if (chunkingDir != null)
                            {
                                chunkingDir.RefreshAsync().Wait();

                                if (chunkingDir.ExistsAsync.Result)
                                {
                                    OnBeforeRollbackChunk.SafeInvokeAsync(chunkingDir).Wait();
                                    OnBeforeRemove.SafeInvokeAsync(chunkingDir).Wait();
                                    chunkingDir.DeleteAsync().Wait();
                                    OnAfterRemove.SafeInvokeAsync(chunkingDir).Wait();
                                    OnAfterRollbackChunk.SafeInvokeAsync(chunkingDir).Wait();
                                }
                            }

                            if (uploadFileInfo != null && chunkedUploadInfo.IsFileTouched)
                            {
                                uploadFileInfo.RefreshAsync().Wait();

                                if (uploadFileInfo.ExistsAsync.Result)
                                {
                                    OnBeforeRollbackChunk.SafeInvokeAsync(uploadFileInfo).Wait();
                                    OnBeforeRemove.SafeInvokeAsync(uploadFileInfo).Wait();
                                    uploadFileInfo.DeleteAsync().Wait();
                                    OnAfterRemove.SafeInvokeAsync(uploadFileInfo).Wait();
                                    OnAfterRollbackChunk.SafeInvokeAsync(uploadFileInfo).Wait();
                                }
                            }
                        }
                    }

                    await OnUploadError.SafeInvokeAsync(ex);
                    throw ex;
                }
            }
            else
            {
                var uploadCount = cmd.Upload.Count();
                for (var idx = 0; idx < uploadCount; idx++)
                {
                    var formFile = cmd.Upload.ElementAt(idx);
                    IDirectory dest = null;
                    IDirectory finalDest = null;
                    string destHash = null;
                    string uploadingFileName = "unknown", cleanFileName;

                    try
                    {
                        (string UploadFileName, int CurrentChunkNo, int TotalChunks)? chunkInfo = null;

                        if (isChunking)
                        {
                            chunkInfo = cmd.ChunkInfo;
                            uploadingFileName = Path.GetFileName(chunkInfo.Value.UploadFileName);
                            cleanFileName = Path.GetFileName(cmd.Chunk);
                        }
                        else
                        {
                            uploadingFileName = Path.GetFileName(formFile.FileName);
                            cleanFileName = uploadingFileName;
                        }

                        if (volume.UploadOrder != null)
                        {
                            var mimeType = MimeHelper.GetMimeType(Path.GetExtension(uploadingFileName));
                            var constraintMap = new Dictionary<UploadConstraintType, IEnumerable<string>>
                            {
                                [UploadConstraintType.Allow] = volume.UploadAllow,
                                [UploadConstraintType.Deny] = volume.UploadDeny,
                            };

                            foreach (var constraintType in volume.UploadOrder)
                            {
                                var constraint = constraintMap[constraintType];
                                if (constraint == null) continue;
                                switch (constraintType)
                                {
                                    case UploadConstraintType.Allow:
                                        {
                                            if (!constraint.Contains(UploadConstants.UploadConstraintAllValue)
                                                && !constraint.Contains(mimeType)
                                                && !constraint.Contains(mimeType.Type)) throw new FileTypeNotAllowException();
                                            break;
                                        }
                                    case UploadConstraintType.Deny:
                                        {
                                            if (constraint.Contains(UploadConstants.UploadConstraintAllValue)
                                                || constraint.Contains(mimeType)
                                                || constraint.Contains(mimeType.Type)) throw new FileTypeNotAllowException();
                                            break;
                                        }
                                }
                            }
                        }

                        if (cmd.UploadPath.Count > idx)
                        {
                            if (isFinalUploading)
                            {
                                dest = cmd.UploadPathInfos.ElementAt(idx).Directory;
                                finalDest = dest;
                                destHash = cmd.UploadPath[idx];
                            }
                            else
                            {
                                finalDest = cmd.UploadPathInfos.ElementAt(idx).Directory;
                                var tempDest = GetChunkDirectory(finalDest, uploadingFileName, cmd.Cid);
                                dest = new FileSystemDirectory(tempDest, volume);
                                destHash = cmd.UploadPath[idx];
                            }
                        }
                        else
                        {
                            if (isFinalUploading)
                            {
                                dest = targetPath.Directory;
                                finalDest = dest;
                                destHash = targetPath.HashedTarget;
                            }
                            else
                            {
                                finalDest = targetPath.Directory;
                                var tempDest = GetChunkDirectory(finalDest, uploadingFileName, cmd.Cid);
                                dest = new FileSystemDirectory(tempDest, volume);
                                destHash = targetPath.HashedTarget;
                            }
                        }

                        if (isChunking)
                        {
                            var chunkedUploadInfo = connectorManager.GetLock(dest.FullName, _ => new ChunkedUploadInfo());
                            lock (chunkedUploadInfo)
                            {
                                if (chunkedUploadInfo.Exception != null) throw chunkedUploadInfo.Exception;

                                if (!dest.ExistsAsync.Result)
                                {
                                    if (!dest.CanCreate()) throw new PermissionDeniedException();

                                    chunkedUploadInfo.TotalUploaded = 0;
                                    OnBeforeMakeDir.SafeInvokeAsync(dest).Wait();
                                    dest.CreateAsync(cancellationToken: cancellationToken).Wait();
                                    OnAfterMakeDir.SafeInvokeAsync(dest).Wait();

                                    WriteStatusFileAsync(dest).Wait();
                                }
                            }
                        }

                        if (!finalDest.CanCreateObject())
                            throw new PermissionDeniedException($"Permission denied: {volume.GetRelativePath(finalDest)}");

                        var uploadFullName = PathHelper.SafelyCombine(dest.FullName, dest.FullName, cleanFileName);
                        var uploadFileInfo = new FileSystemFile(uploadFullName, volume);
                        var finalUploadFullName = PathHelper.SafelyCombine(finalDest.FullName, finalDest.FullName, uploadingFileName);
                        var finalUploadFileInfo = isChunking ? new FileSystemFile(finalUploadFullName, volume) : uploadFileInfo;
                        var isOverwrite = false;

                        if (!isFinalUploading && await uploadFileInfo.ExistsAsync)
                        {
                            throw new PermissionDeniedException();
                        }

                        if (await finalUploadFileInfo.ExistsAsync)
                        {
                            if (cmd.Renames.Contains(uploadingFileName))
                            {
                                var fileNameWithoutExt = Path.GetFileNameWithoutExtension(uploadingFileName);
                                var ext = Path.GetExtension(uploadingFileName);
                                var backupName = $"{fileNameWithoutExt}{cmd.Suffix}{ext}";
                                var fullBakName = PathHelper.SafelyCombine(finalUploadFileInfo.Parent.FullName, finalUploadFileInfo.Parent.FullName, backupName);
                                var bakFile = new FileSystemFile(fullBakName, volume);

                                if (await bakFile.ExistsAsync)
                                    backupName = await bakFile.GetCopyNameAsync(cmd.Suffix, cancellationToken: cancellationToken);

                                var prevName = finalUploadFileInfo.Name;
                                await OnBeforeRename.SafeInvokeAsync(finalUploadFileInfo, backupName);
                                await finalUploadFileInfo.RenameAsync(backupName, cancellationToken: cancellationToken);
                                await OnAfterRename.SafeInvokeAsync(finalUploadFileInfo, prevName);

                                uploadResp.added.Add(await finalUploadFileInfo.ToFileInfoAsync(destHash, volume, pathParser, pictureEditor, videoEditor, cancellationToken: cancellationToken));
                                finalUploadFileInfo = new FileSystemFile(finalUploadFullName, volume);
                            }
                            else if (cmd.Overwrite == 0 || (cmd.Overwrite == null && !volume.UploadOverwrite))
                            {
                                string newName = await finalUploadFileInfo.GetCopyNameAsync(cmd.Suffix, cancellationToken: cancellationToken);
                                finalUploadFullName = PathHelper.SafelyCombine(finalUploadFileInfo.DirectoryName, finalUploadFileInfo.DirectoryName, newName);
                                finalUploadFileInfo = new FileSystemFile(finalUploadFullName, volume);
                                isOverwrite = false;
                            }
                            else if (!finalUploadFileInfo.ObjectAttribute.Write)
                                throw new PermissionDeniedException();
                            else isOverwrite = true;
                        }

                        uploadFileInfo = isChunking ? uploadFileInfo : finalUploadFileInfo;

                        if (isChunking)
                        {
                            await WriteStatusFileAsync(dest);
                        }

                        await OnBeforeUpload.SafeInvokeAsync(uploadFileInfo, finalUploadFileInfo, formFile, isOverwrite, isChunking);
                        using (var fileStream = await uploadFileInfo.OpenWriteAsync(cancellationToken: cancellationToken))
                        {
                            await formFile.CopyToAsync(fileStream, cancellationToken: cancellationToken);
                        }
                        await OnAfterUpload.SafeInvokeAsync(uploadFileInfo, finalUploadFileInfo, formFile, isOverwrite, isChunking);

                        if (isFinalUploading)
                        {
                            await finalUploadFileInfo.RefreshAsync(cancellationToken);
                            uploadResp.added.Add(await finalUploadFileInfo.ToFileInfoAsync(destHash, volume, pathParser, pictureEditor, videoEditor, cancellationToken: cancellationToken));
                        }
                        else
                        {
                            var chunkedUploadInfo = connectorManager.GetLock<ChunkedUploadInfo>(dest.FullName);

                            if (chunkedUploadInfo != null)
                            {
                                lock (chunkedUploadInfo)
                                {
                                    if (chunkedUploadInfo.Exception != null) throw chunkedUploadInfo.Exception;

                                    chunkedUploadInfo.TotalUploaded++;

                                    if (chunkedUploadInfo.TotalUploaded == cmd.ChunkInfo.TotalChunks)
                                    {
                                        uploadResp._chunkmerged = dest.Name;
                                        uploadResp._name = uploadingFileName;
                                    }
                                }
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        var rootCause = ex.GetRootCause();

                        if (isChunking && dest != null)
                        {
                            var chunkedUploadInfo = connectorManager.GetLock<ChunkedUploadInfo>(dest.FullName);
                            var isExceptionReturned = false;

                            if (chunkedUploadInfo != null)
                            {
                                lock (chunkedUploadInfo)
                                {
                                    isExceptionReturned = chunkedUploadInfo.Exception != null;

                                    if (!isExceptionReturned)
                                    {
                                        chunkedUploadInfo.Exception = rootCause;
                                    }

                                    if (dest != null)
                                    {
                                        dest.RefreshAsync().Wait();

                                        if (dest.ExistsAsync.Result)
                                        {
                                            OnBeforeRollbackChunk.SafeInvokeAsync(dest).Wait();
                                            OnBeforeRemove.SafeInvokeAsync(dest).Wait();
                                            dest.DeleteAsync().Wait();
                                            OnAfterRemove.SafeInvokeAsync(dest).Wait();
                                            OnAfterRollbackChunk.SafeInvokeAsync(dest).Wait();
                                        }
                                    }
                                }
                            }

                            if (isExceptionReturned) return new UploadResponse();

                            await OnUploadError.SafeInvokeAsync(ex);
                            throw ex;
                        }

                        await OnUploadError.SafeInvokeAsync(ex);

                        if (rootCause is PermissionDeniedException pEx)
                        {
                            warning.Add(string.IsNullOrEmpty(pEx.Message) ? $"Permission denied: {uploadingFileName}" : pEx.Message);
                            warningDetails.Add(ErrorResponse.Factory.UploadFile(pEx, uploadingFileName));
                        }
                        else if (rootCause is FileTypeNotAllowException fileTypeEx)
                        {
                            throw fileTypeEx;
                        }
                        else
                        {
                            warning.Add($"Failed to upload: {uploadingFileName}");
                            warningDetails.Add(ErrorResponse.Factory.UploadFile(ex, uploadingFileName));
                        }
                    }
                }
            }

            return uploadResp;
        }

        private string GetChunkDirectory(IDirectory uploadDir, string uploadingFileName, string cid)
        {
            var bytes = Encoding.UTF8.GetBytes(uploadDir.FullName + uploadingFileName + cid);
            var signature = BitConverter.ToString(cryptographyProvider.HMACSHA1ComputeHash(
                nameof(GetChunkDirectory), bytes)).Replace("-", string.Empty);
            var tempFileName = $"{ChunkingFolderPrefix}_{signature}";
            var tempDest = PathHelper.SafelyCombine(uploadDir.Volume.ChunkDirectory, uploadDir.Volume.ChunkDirectory, tempFileName);
            return tempDest;
        }

        private async Task WriteStatusFileAsync(IDirectory directory)
        {
            try
            {
                if (await directory.ExistsAsync)
                {
                    var statusFile = PathHelper.SafelyCombine(directory.FullName, directory.FullName, tempFileCleaner.Options.StatusFile);
                    using (var file = File.OpenWrite(statusFile)) { }
                }
            }
            catch (Exception) { }
        }

        class ChunkedUploadInfo : ConnectorLock
        {
            public Exception Exception { get; set; }
            public int TotalUploaded { get; set; }
            public bool IsFileTouched { get; set; }
        }
    }
trannamtrung1st commented 2 years ago

Hi @benny-adiwijaya , I think you don't need to override the events of the base FileSystemDriver, maybe you're overriding the right one. So in the FileControllers, it is trying to invoke the event in the base class I guess.

benny-adiwijaya commented 2 years ago

I think I dont override the events, I can override uploadAsync and invoke event without problem in the previous version. can you show me sample code how to override uploadAsync the correct way?

trannamtrung1st commented 2 years ago

Seems that it is the limitation of using events. Let me try some workaround.

trannamtrung1st commented 2 years ago

Hi please take a look at my new lib version (PR: #29 ). Thanks for pointing out this limitation. The API may not be quite consistent for now but hope it helps. After upgrading the packages, you will be able to override the method without the need to override the events anymore.

benny-adiwijaya commented 2 years ago

Hi, thank you for your response. After upgrade to new version, unfortunately I have another issue. It seem in my project the CustomizeResponse not work as expected. There is error in client says "Invalid backend response. Data is not JSON."

When I take out event command in SetupConnectorAsync, it works as expected.

I do have some modification on CustomizeResponse method, but it work on previous version.

here is my code

[Route("connector")]
        [HttpPost]
        [HttpGet]
        [Authorize]
        [ProducesResponseType(StatusCodes.Status200OK)]
        [ProducesResponseType(StatusCodes.Status500InternalServerError)]
        public async Task<IActionResult> Connector()
        {
            var location = GetControllerActionNames();
            try
            {
                var ccTokenSource = ConnectorHelper.RegisterCcTokenSource(HttpContext);
                var volumes = await SetupConnectorAsync(ccTokenSource.Token);
                var cmd = ConnectorHelper.ParseCommand(Request);
                var conResult = await _connector.ProcessAsync(cmd, ccTokenSource);

                switch (cmd.Cmd)
                {
                    case ConnectorCommand.Cmd_Open:
                        {
                            var getCmdObject = (OpenCommand)cmd.CmdObject;
                            var volumeId = getCmdObject.TargetPath.Volume.VolumeId;
                            var volume = volumes.SingleOrDefault(q => q.VolumeId == volumeId);
                            CustomizeResponse(conResult, volume);
                            break;
                        }
                }

                var actionResult = conResult.ToActionResult(HttpContext);

                return actionResult;
            }
            catch (Exception e)
            {
                return InternalError($"{location}: {e.Message} - {e.InnerException}");
            }
        }

        private void CustomizeResponse(ConnectorResult connectorResult, IVolume volume)
        {

            var storageCache = _storageManager.GetOrCreateDirectoryStorage(volume.RootDirectory,
                    (dir) => volume.Driver.CreateDirectory(dir, volume).GetPhysicalStorageUsageAsync(HttpContext.RequestAborted));

            if (connectorResult.Response is InitResponse initResp)
            {
                connectorResult.Response = new ApplicationInitResponse(initResp)
                {
                    volume = volume,
                    usage = storageCache.Storage
                };
            }
            else if (connectorResult.Response is OpenResponse openResp)
            {
                connectorResult.Response = new ApplicationOpenResponse(openResp)
                {
                    volume = volume,
                    usage = storageCache.Storage
                };
            }

        }

private async Task<IList<IVolume>> SetupConnectorAsync(CancellationToken cancellationToken)
        {
            try
            {
                cancellationToken.ThrowIfCancellationRequested();

                var userId = User.FindFirstValue(ClaimTypes.Sid);

                var userFolders = await _userFolderRepository.FindByUser(userId);

                // Quota management: The 2 line belows is setup once per request
                var quotaOptions = new QuotaOptions() { Enabled = true };
                _connector.PluginManager.Features[typeof(QuotaOptions)] = quotaOptions;

                var volumes = new List<IVolume>();

                foreach (var uf in userFolders)
                {
                    var volumePath = uf.Folder.Path;

                    var volume = new Volume(_driver,
                        MapStoragePath($"{volumePath}"),
                        MapStoragePath($"{uf.Folder.Storage.Path}/.temp"),
                        $"/api/FileSystem/storage/{volumePath}/",
                        $"/api/FileSystem/thumb/",
                        thumbnailDirectory: MapStoragePath($"{uf.Folder.Storage.Path}/.thumb/{uf.Folder.Name}"))
                    {
                        Name = uf.Folder.Name,
                        IsReadOnly = uf.IsReadOnly,
                        MaxUploadSize = uf.Folder.Quota,
                        MaxUploadConnections = 3,
                        VolumeId = uf.FolderId.ToString() + "~" + uf.Folder.Name + "_"

                    };

                    _connector.AddVolume(volume);
                    await _driver.SetupVolumeAsync(volume, cancellationToken);

                    // Quota management: This is set up per volume. Use VolumeId as key.
                    // The plugin support quota management on Volume (root) level only. It means that you can not set quota for directories.
                    quotaOptions.Quotas[volume.VolumeId] = new VolumeQuota
                    {
                        VolumeId = volume.VolumeId,
                        MaxStorageSize = uf.Folder.Quota,
                    };

                    volumes.Add(volume);
                }

                // Events
                _driver.OnBeforeUpload.Add((file, destFile, formFile, isOverwrite, isChunking) =>
                {
                    //UpdatePulseStatus();
                    return Task.CompletedTask;
                });

                _driver.OnAfterUpload.Add((file, destFile, formFile, isOverwrite, isChunking) =>
                {
                    if (!isChunking)
                    {
                        Console.WriteLine($"Uploaded to: {destFile?.FullName}");
                    }

                    return Task.CompletedTask;
                });

                _driver.OnAfterChunkMerged.Add((file, isOverwrite) =>
                {
                    return Task.CompletedTask;
                });

                return volumes;

            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                return null;
            }
        }

Do you know what might the cause of the problem?

trannamtrung1st commented 2 years ago

can you do a try catch to see what happened? that would help for easier debugging.

benny-adiwijaya commented 2 years ago

I already do a try catch but there is no exception in the server. After some checking I think the problem because I attach volume in the response to client and when there is event there is property that cannot be convert to json

Screen Shot 2022-03-20 at 1 15 03 AM

I already take out the volume from response and now its working fine thank you

trannamtrung1st commented 2 years ago

Yeah glad to hear that. The volume should not be returned directly to the client. So I'll close this case here. Thanks.