// (c) Copyright Ascensio System SIA 2010-2022 // // This program is a free software product. // You can redistribute it and/or modify it under the terms // of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software // Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended // to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of // any third-party rights. // // This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty // of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see // the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html // // You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021. // // The interactive user interfaces in modified source and object code versions of the Program must // display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3. // // Pursuant to Section 7(b) of the License you must retain the original Product logo when // distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under // trademark law for use of our trademarks. // // All the Product's GUI elements, including illustrations and icon sets, as well as technical writing // content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0 // International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode namespace ASC.Files.Api; public class FilesController : ApiControllerBase { private readonly IServiceProvider _serviceProvider; private readonly GlobalFolderHelper _globalFolderHelper; private readonly FileStorageService _fileStorageServiceString; private readonly FilesControllerHelper _filesControllerHelperInt; private readonly FilesControllerHelper _filesControllerHelperString; public FilesController( IServiceProvider serviceProvider, GlobalFolderHelper globalFolderHelper, FileStorageService fileStorageServiceString, FilesControllerHelper filesControllerHelperInt, FilesControllerHelper filesControllerHelperString) { _serviceProvider = serviceProvider; _globalFolderHelper = globalFolderHelper; _fileStorageServiceString = fileStorageServiceString; _filesControllerHelperInt = filesControllerHelperInt; _filesControllerHelperString = filesControllerHelperString; } /// /// Change version history /// /// File ID /// Version of history /// Mark as version or revision /// Files /// [Update("file/{fileId}/history")] public Task>> ChangeHistoryFromBodyAsync(string fileId, [FromBody] ChangeHistoryRequestDto inDto) { return _filesControllerHelperString.ChangeHistoryAsync(fileId, inDto.Version, inDto.ContinueVersion); } [Update("file/{fileId:int}/history")] public Task>> ChangeHistoryFromBodyAsync(int fileId, [FromBody] ChangeHistoryRequestDto inDto) { return _filesControllerHelperInt.ChangeHistoryAsync(fileId, inDto.Version, inDto.ContinueVersion); } [Update("file/{fileId}/history")] [Consumes("application/x-www-form-urlencoded")] public Task>> ChangeHistoryFromFormAsync(string fileId, [FromForm] ChangeHistoryRequestDto inDto) { return _filesControllerHelperString.ChangeHistoryAsync(fileId, inDto.Version, inDto.ContinueVersion); } [Update("file/{fileId:int}/history")] [Consumes("application/x-www-form-urlencoded")] public Task>> ChangeHistoryFromFormAsync(int fileId, [FromForm] ChangeHistoryRequestDto inDto) { return _filesControllerHelperInt.ChangeHistoryAsync(fileId, inDto.Version, inDto.ContinueVersion); } /// /// Check conversion status /// /// Convert /// File operations /// /// /// Operation result [Read("file/{fileId}/checkconversion")] public IAsyncEnumerable> CheckConversionAsync(string fileId, bool start) { return _filesControllerHelperString.CheckConversionAsync(new CheckConversionRequestDto() { FileId = fileId, StartConvert = start }); } [Read("file/{fileId:int}/checkconversion")] public IAsyncEnumerable> CheckConversionAsync(int fileId, bool start) { return _filesControllerHelperInt.CheckConversionAsync(new CheckConversionRequestDto() { FileId = fileId, StartConvert = start }); } [Create("file/{fileId:int}/copyas", order: int.MaxValue - 1)] public object CopyFileAsFromBody(int fileId, [FromBody] CopyAsRequestDto inDto) { return CopyFile(fileId, inDto); } [Create("file/{fileId}/copyas", order: int.MaxValue)] public object CopyFileAsFromBody(string fileId, [FromBody] CopyAsRequestDto inDto) { return CopyFile(fileId, inDto); } [Create("file/{fileId:int}/copyas", order: int.MaxValue - 1)] [Consumes("application/x-www-form-urlencoded")] public object CopyFileAsFromForm(int fileId, [FromForm] CopyAsRequestDto inDto) { return CopyFile(fileId, inDto); } [Create("file/{fileId}/copyas", order: int.MaxValue)] [Consumes("application/x-www-form-urlencoded")] public object CopyFileAsFromForm(string fileId, [FromForm] CopyAsRequestDto inDto) { return CopyFile(fileId, inDto); } /// /// Creates a new file in the 'My Documents' section with the title sent in the request /// /// Create file /// File Creation /// File title /// In case the extension for the file title differs from DOCX/XLSX/PPTX and belongs to one of the known text, spreadsheet or presentation formats, it will be changed to DOCX/XLSX/PPTX accordingly. If the file extension is not set or is unknown, the DOCX extension will be added to the file title. /// New file info [Create("@my/file")] public Task> CreateFileFromBodyAsync([FromBody] CreateFileRequestDto inDto) { return _filesControllerHelperInt.CreateFileAsync(_globalFolderHelper.FolderMy, inDto.Title, inDto.TemplateId, inDto.EnableExternalExt); } /// /// Creates a new file in the specified folder with the title sent in the request /// /// Create file /// File Creation /// Folder ID /// File title /// In case the extension for the file title differs from DOCX/XLSX/PPTX and belongs to one of the known text, spreadsheet or presentation formats, it will be changed to DOCX/XLSX/PPTX accordingly. If the file extension is not set or is unknown, the DOCX extension will be added to the file title. /// New file info [Create("{folderId}/file")] public Task> CreateFileFromBodyAsync(string folderId, [FromBody] CreateFileRequestDto inDto) { return _filesControllerHelperString.CreateFileAsync(folderId, inDto.Title, inDto.TemplateId, inDto.EnableExternalExt); } [Create("{folderId:int}/file")] public Task> CreateFileFromBodyAsync(int folderId, [FromBody] CreateFileRequestDto inDto) { return _filesControllerHelperInt.CreateFileAsync(folderId, inDto.Title, inDto.TemplateId, inDto.EnableExternalExt); } [Create("@my/file")] [Consumes("application/x-www-form-urlencoded")] public Task> CreateFileFromFormAsync([FromForm] CreateFileRequestDto inDto) { return _filesControllerHelperInt.CreateFileAsync(_globalFolderHelper.FolderMy, inDto.Title, inDto.TemplateId, inDto.EnableExternalExt); } [Create("{folderId}/file")] [Consumes("application/x-www-form-urlencoded")] public Task> CreateFileFromFormAsync(string folderId, [FromForm] CreateFileRequestDto inDto) { return _filesControllerHelperString.CreateFileAsync(folderId, inDto.Title, inDto.TemplateId, inDto.EnableExternalExt); } [Create("{folderId:int}/file")] [Consumes("application/x-www-form-urlencoded")] public Task> CreateFileFromFormAsync(int folderId, [FromForm] CreateFileRequestDto inDto) { return _filesControllerHelperInt.CreateFileAsync(folderId, inDto.Title, inDto.TemplateId, inDto.EnableExternalExt); } /// /// Creates an html (.html) file in the selected folder with the title and contents sent in the request /// /// Create html /// File Creation /// Folder ID /// File title /// File contents /// Folder contents [Create("{folderId}/html")] public Task> CreateHtmlFileFromBodyAsync(string folderId, [FromBody] CreateTextOrHtmlFileRequestDto inDto) { return _filesControllerHelperString.CreateHtmlFileAsync(folderId, inDto.Title, inDto.Content); } [Create("{folderId:int}/html")] public Task> CreateHtmlFileFromBodyAsync(int folderId, [FromBody] CreateTextOrHtmlFileRequestDto inDto) { return _filesControllerHelperInt.CreateHtmlFileAsync(folderId, inDto.Title, inDto.Content); } [Create("{folderId}/html")] [Consumes("application/x-www-form-urlencoded")] public Task> CreateHtmlFileFromFormAsync(string folderId, [FromForm] CreateTextOrHtmlFileRequestDto inDto) { return _filesControllerHelperString.CreateHtmlFileAsync(folderId, inDto.Title, inDto.Content); } [Create("{folderId:int}/html")] [Consumes("application/x-www-form-urlencoded")] public Task> CreateHtmlFileFromFormAsync(int folderId, [FromForm] CreateTextOrHtmlFileRequestDto inDto) { return _filesControllerHelperInt.CreateHtmlFileAsync(folderId, inDto.Title, inDto.Content); } /// /// Creates an html (.html) file in 'Common Documents' section with the title and contents sent in the request /// /// Create html in 'Common' /// File Creation /// File title /// File contents /// Folder contents [Create("@common/html")] public async Task> CreateHtmlFileInCommonFromBodyAsync([FromBody] CreateTextOrHtmlFileRequestDto inDto) { return await _filesControllerHelperInt.CreateHtmlFileAsync(await _globalFolderHelper.FolderCommonAsync, inDto.Title, inDto.Content); } [Create("@common/html")] [Consumes("application/x-www-form-urlencoded")] public async Task> CreateHtmlFileInCommonFromFormAsync([FromForm] CreateTextOrHtmlFileRequestDto inDto) { return await _filesControllerHelperInt.CreateHtmlFileAsync(await _globalFolderHelper.FolderCommonAsync, inDto.Title, inDto.Content); } /// /// Creates an html (.html) file in 'My Documents' section with the title and contents sent in the request /// /// Create html in 'My' /// File Creation /// File title /// File contents /// Folder contents [Create("@my/html")] public Task> CreateHtmlFileInMyFromBodyAsync([FromBody] CreateTextOrHtmlFileRequestDto inDto) { return _filesControllerHelperInt.CreateHtmlFileAsync(_globalFolderHelper.FolderMy, inDto.Title, inDto.Content); } [Create("@my/html")] [Consumes("application/x-www-form-urlencoded")] public Task> CreateHtmlFileInMyFromFormAsync([FromForm] CreateTextOrHtmlFileRequestDto inDto) { return _filesControllerHelperInt.CreateHtmlFileAsync(_globalFolderHelper.FolderMy, inDto.Title, inDto.Content); } /// /// Creates a text (.txt) file in the selected folder with the title and contents sent in the request /// /// Create txt /// File Creation /// Folder ID /// File title /// File contents /// Folder contents [Create("{folderId}/text")] public Task> CreateTextFileFromBodyAsync(string folderId, [FromBody] CreateTextOrHtmlFileRequestDto inDto) { return _filesControllerHelperString.CreateTextFileAsync(folderId, inDto.Title, inDto.Content); } [Create("{folderId:int}/text")] public Task> CreateTextFileFromBodyAsync(int folderId, [FromBody] CreateTextOrHtmlFileRequestDto inDto) { return _filesControllerHelperInt.CreateTextFileAsync(folderId, inDto.Title, inDto.Content); } [Create("{folderId}/text")] [Consumes("application/x-www-form-urlencoded")] public Task> CreateTextFileFromFormAsync(string folderId, [FromForm] CreateTextOrHtmlFileRequestDto inDto) { return _filesControllerHelperString.CreateTextFileAsync(folderId, inDto.Title, inDto.Content); } [Create("{folderId:int}/text")] [Consumes("application/x-www-form-urlencoded")] public Task> CreateTextFileFromFormAsync(int folderId, [FromForm] CreateTextOrHtmlFileRequestDto inDto) { return _filesControllerHelperInt.CreateTextFileAsync(folderId, inDto.Title, inDto.Content); } /// /// Creates a text (.txt) file in 'Common Documents' section with the title and contents sent in the request /// /// Create txt in 'Common' /// File Creation /// File title /// File contents /// Folder contents [Create("@common/text")] public async Task> CreateTextFileInCommonFromBodyAsync([FromBody] CreateTextOrHtmlFileRequestDto inDto) { return await _filesControllerHelperInt.CreateTextFileAsync(await _globalFolderHelper.FolderCommonAsync, inDto.Title, inDto.Content); } [Create("@common/text")] [Consumes("application/x-www-form-urlencoded")] public async Task> CreateTextFileInCommonFromFormAsync([FromForm] CreateTextOrHtmlFileRequestDto inDto) { return await _filesControllerHelperInt.CreateTextFileAsync(await _globalFolderHelper.FolderCommonAsync, inDto.Title, inDto.Content); } /// /// Creates a text (.txt) file in 'My Documents' section with the title and contents sent in the request /// /// Create txt in 'My' /// File Creation /// File title /// File contents /// Folder contents [Create("@my/text")] public Task> CreateTextFileInMyFromBodyAsync([FromBody] CreateTextOrHtmlFileRequestDto inDto) { return _filesControllerHelperInt.CreateTextFileAsync(_globalFolderHelper.FolderMy, inDto.Title, inDto.Content); } [Create("@my/text")] [Consumes("application/x-www-form-urlencoded")] public Task> CreateTextFileInMyFromFormAsync([FromForm] CreateTextOrHtmlFileRequestDto inDto) { return _filesControllerHelperInt.CreateTextFileAsync(_globalFolderHelper.FolderMy, inDto.Title, inDto.Content); } [Create("thumbnails")] public Task> CreateThumbnailsFromBodyAsync([FromBody] BaseBatchRequestDto inDto) { return _fileStorageServiceString.CreateThumbnailsAsync(inDto.FileIds.ToList()); } [Create("thumbnails")] [Consumes("application/x-www-form-urlencoded")] public async Task> CreateThumbnailsFromFormAsync([FromForm][ModelBinder(BinderType = typeof(BaseBatchModelBinder))] BaseBatchRequestDto inDto) { return await _fileStorageServiceString.CreateThumbnailsAsync(inDto.FileIds.ToList()); } /// /// Deletes the file with the ID specified in the request /// /// Delete file /// Files /// File ID /// Delete after finished /// Don't move to the Recycle Bin /// Operation result [Delete("file/{fileId}", order: int.MaxValue, DisableFormat = true)] public Task> DeleteFile(string fileId, [FromBody] DeleteRequestDto inDto) { return _filesControllerHelperString.DeleteFileAsync(fileId, inDto.DeleteAfter, inDto.Immediately); } [Delete("file/{fileId:int}", order: int.MaxValue - 1, DisableFormat = true)] public Task> DeleteFile(int fileId, [FromBody] DeleteRequestDto inDto) { return _filesControllerHelperInt.DeleteFileAsync(fileId, inDto.DeleteAfter, inDto.Immediately); } [AllowAnonymous] [Read("file/{fileId}/edit/diff")] public Task GetEditDiffUrlAsync(string fileId, int version = 0, string doc = null) { return _filesControllerHelperString.GetEditDiffUrlAsync(fileId, version, doc); } [AllowAnonymous] [Read("file/{fileId:int}/edit/diff")] public Task GetEditDiffUrlAsync(int fileId, int version = 0, string doc = null) { return _filesControllerHelperInt.GetEditDiffUrlAsync(fileId, version, doc); } [AllowAnonymous] [Read("file/{fileId}/edit/history")] public Task> GetEditHistoryAsync(string fileId, string doc = null) { return _filesControllerHelperString.GetEditHistoryAsync(fileId, doc); } [AllowAnonymous] [Read("file/{fileId:int}/edit/history")] public Task> GetEditHistoryAsync(int fileId, string doc = null) { return _filesControllerHelperInt.GetEditHistoryAsync(fileId, doc); } /// /// Returns a detailed information about the file with the ID specified in the request /// /// File information /// Files /// File info [Read("file/{fileId}", order: int.MaxValue, DisableFormat = true)] public Task> GetFileInfoAsync(string fileId, int version = -1) { return _filesControllerHelperString.GetFileInfoAsync(fileId, version); } [Read("file/{fileId:int}")] public Task> GetFileInfoAsync(int fileId, int version = -1) { return _filesControllerHelperInt.GetFileInfoAsync(fileId, version); } /// /// Returns the detailed information about all the available file versions with the ID specified in the request /// /// File versions /// Files /// File ID /// File information [Read("file/{fileId}/history")] public Task>> GetFileVersionInfoAsync(string fileId) { return _filesControllerHelperString.GetFileVersionInfoAsync(fileId); } [Read("file/{fileId:int}/history")] public Task>> GetFileVersionInfoAsync(int fileId) { return _filesControllerHelperInt.GetFileVersionInfoAsync(fileId); } [Update("file/{fileId}/lock")] public Task> LockFileFromBodyAsync(string fileId, [FromBody] LockFileRequestDto inDto) { return _filesControllerHelperString.LockFileAsync(fileId, inDto.LockFile); } [Update("file/{fileId:int}/lock")] public Task> LockFileFromBodyAsync(int fileId, [FromBody] LockFileRequestDto inDto) { return _filesControllerHelperInt.LockFileAsync(fileId, inDto.LockFile); } [Update("file/{fileId}/lock")] [Consumes("application/x-www-form-urlencoded")] public Task> LockFileFromFormAsync(string fileId, [FromForm] LockFileRequestDto inDto) { return _filesControllerHelperString.LockFileAsync(fileId, inDto.LockFile); } [Update("file/{fileId:int}/lock")] [Consumes("application/x-www-form-urlencoded")] public Task> LockFileFromFormAsync(int fileId, [FromForm] LockFileRequestDto inDto) { return _filesControllerHelperInt.LockFileAsync(fileId, inDto.LockFile); } [AllowAnonymous] [Read("file/{fileId}/restoreversion")] public Task> RestoreVersionAsync(string fileId, int version = 0, string url = null, string doc = null) { return _filesControllerHelperString.RestoreVersionAsync(fileId, version, url, doc); } [AllowAnonymous] [Read("file/{fileId:int}/restoreversion")] public Task> RestoreVersionAsync(int fileId, int version = 0, string url = null, string doc = null) { return _filesControllerHelperInt.RestoreVersionAsync(fileId, version, url, doc); } /// /// Start conversion /// /// Convert /// File operations /// /// Operation result [Update("file/{fileId}/checkconversion")] public IAsyncEnumerable> StartConversion(string fileId, [FromBody(EmptyBodyBehavior = Microsoft.AspNetCore.Mvc.ModelBinding.EmptyBodyBehavior.Allow)] CheckConversionRequestDto inDto) { if (inDto == null) { inDto = new CheckConversionRequestDto(); } inDto.FileId = fileId; return _filesControllerHelperString.StartConversionAsync(inDto); } [Update("file/{fileId:int}/checkconversion")] public IAsyncEnumerable> StartConversion(int fileId, [FromBody(EmptyBodyBehavior = Microsoft.AspNetCore.Mvc.ModelBinding.EmptyBodyBehavior.Allow)] CheckConversionRequestDto inDto) { if (inDto == null) { inDto = new CheckConversionRequestDto(); } inDto.FileId = fileId; return _filesControllerHelperInt.StartConversionAsync(inDto); } [Update("file/{fileId}/comment")] public async Task UpdateCommentFromBodyAsync(string fileId, [FromBody] UpdateCommentRequestDto inDto) { return await _filesControllerHelperString.UpdateCommentAsync(fileId, inDto.Version, inDto.Comment); } [Update("file/{fileId:int}/comment")] public async Task UpdateCommentFromBodyAsync(int fileId, [FromBody] UpdateCommentRequestDto inDto) { return await _filesControllerHelperInt.UpdateCommentAsync(fileId, inDto.Version, inDto.Comment); } [Update("file/{fileId}/comment")] [Consumes("application/x-www-form-urlencoded")] public async Task UpdateCommentFromFormAsync(string fileId, [FromForm] UpdateCommentRequestDto inDto) { return await _filesControllerHelperString.UpdateCommentAsync(fileId, inDto.Version, inDto.Comment); } [Update("file/{fileId:int}/comment")] [Consumes("application/x-www-form-urlencoded")] public async Task UpdateCommentFromFormAsync(int fileId, [FromForm] UpdateCommentRequestDto inDto) { return await _filesControllerHelperInt.UpdateCommentAsync(fileId, inDto.Version, inDto.Comment); } /// /// Updates the information of the selected file with the parameters specified in the request /// /// Update file info /// Files /// File ID /// New title /// File last version number /// File info [Update("file/{fileId}", order: int.MaxValue, DisableFormat = true)] public Task> UpdateFileFromBodyAsync(string fileId, [FromBody] UpdateFileRequestDto inDto) { return _filesControllerHelperString.UpdateFileAsync(fileId, inDto.Title, inDto.LastVersion); } [Update("file/{fileId:int}", order: int.MaxValue - 1, DisableFormat = true)] public Task> UpdateFileFromBodyAsync(int fileId, [FromBody] UpdateFileRequestDto inDto) { return _filesControllerHelperInt.UpdateFileAsync(fileId, inDto.Title, inDto.LastVersion); } [Update("file/{fileId}", order: int.MaxValue, DisableFormat = true)] [Consumes("application/x-www-form-urlencoded")] public Task> UpdateFileFromFormAsync(string fileId, [FromForm] UpdateFileRequestDto inDto) { return _filesControllerHelperString.UpdateFileAsync(fileId, inDto.Title, inDto.LastVersion); } [Update("file/{fileId:int}", order: int.MaxValue - 1, DisableFormat = true)] [Consumes("application/x-www-form-urlencoded")] public Task> UpdateFileFromFormAsync(int fileId, [FromForm] UpdateFileRequestDto inDto) { return _filesControllerHelperInt.UpdateFileAsync(fileId, inDto.Title, inDto.LastVersion); } /// /// /// /// /// /// /// /// false [Update("{fileId}/update")] public Task> UpdateFileStreamFromFormAsync(string fileId, [FromForm] FileStreamRequestDto inDto) { return _filesControllerHelperString.UpdateFileStreamAsync(_filesControllerHelperInt.GetFileFromRequest(inDto).OpenReadStream(), fileId, inDto.FileExtension, inDto.Encrypted, inDto.Forcesave); } [Update("{fileId:int}/update")] public Task> UpdateFileStreamFromFormAsync(int fileId, [FromForm] FileStreamRequestDto inDto) { return _filesControllerHelperInt.UpdateFileStreamAsync(_filesControllerHelperInt.GetFileFromRequest(inDto).OpenReadStream(), fileId, inDto.FileExtension, inDto.Encrypted, inDto.Forcesave); } private object CopyFile(T fileId, CopyAsRequestDto inDto) { var helper = _serviceProvider.GetService>(); if (inDto.DestFolderId.ValueKind == JsonValueKind.Number) { return helper.CopyFileAsAsync(fileId, inDto.DestFolderId.GetInt32(), inDto.DestTitle, inDto.Password); } else if (inDto.DestFolderId.ValueKind == JsonValueKind.String) { return helper.CopyFileAsAsync(fileId, inDto.DestFolderId.GetString(), inDto.DestTitle, inDto.Password); } return null; } }