diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Microsoft/AspNetCore/Http/AbpFormFileExtensions.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Microsoft/AspNetCore/Http/AbpFormFileExtensions.cs new file mode 100644 index 0000000000..c808250a3e --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Microsoft/AspNetCore/Http/AbpFormFileExtensions.cs @@ -0,0 +1,15 @@ +using System.IO; + +namespace Microsoft.AspNetCore.Http +{ + public static class AbpFormFileExtensions + { + public static byte[] GetAllBytes(this IFormFile file) + { + using (var stream = file.OpenReadStream()) + { + return stream.GetAllBytes(); + } + } + } +} diff --git a/modules/blogging/app/Volo.BloggingTestApp/BloggingTestAppModule.cs b/modules/blogging/app/Volo.BloggingTestApp/BloggingTestAppModule.cs index 1945c6ac31..aec8044d3b 100644 --- a/modules/blogging/app/Volo.BloggingTestApp/BloggingTestAppModule.cs +++ b/modules/blogging/app/Volo.BloggingTestApp/BloggingTestAppModule.cs @@ -114,7 +114,6 @@ namespace Volo.BloggingTestApp Configure(options => { options.FileUploadLocalFolder = Path.Combine(hostingEnvironment.WebRootPath, "files"); - options.FileUploadUrlRoot = "/files/"; }); } diff --git a/modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Files/FileUploadOutputDto.cs b/modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Files/FileUploadOutputDto.cs index 1c3b1a1a94..a5e49eee48 100644 --- a/modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Files/FileUploadOutputDto.cs +++ b/modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Files/FileUploadOutputDto.cs @@ -2,6 +2,8 @@ { public class FileUploadOutputDto { - public string Url { get; set; } + public string Name { get; set; } + + public string WebUrl { get; set; } } } \ No newline at end of file diff --git a/modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Files/IFileAppService.cs b/modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Files/IFileAppService.cs index 6fed8bc62f..a949c848cd 100644 --- a/modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Files/IFileAppService.cs +++ b/modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Files/IFileAppService.cs @@ -5,6 +5,8 @@ namespace Volo.Blogging.Files { public interface IFileAppService : IApplicationService { - Task UploadAsync(FileUploadInputDto input); + Task GetAsync(string name); + + Task CreateAsync(FileUploadInputDto input); } } diff --git a/modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Files/RawFileDto.cs b/modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Files/RawFileDto.cs new file mode 100644 index 0000000000..56a9653b73 --- /dev/null +++ b/modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Files/RawFileDto.cs @@ -0,0 +1,7 @@ +namespace Volo.Blogging.Files +{ + public class RawFileDto + { + public byte[] Bytes { get; set; } + } +} \ No newline at end of file diff --git a/modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/Files/BlogFileOptions.cs b/modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/Files/BlogFileOptions.cs index a06bdafc8d..7243595802 100644 --- a/modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/Files/BlogFileOptions.cs +++ b/modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/Files/BlogFileOptions.cs @@ -7,7 +7,5 @@ public class BlogFileOptions { public string FileUploadLocalFolder { get; set; } - - public string FileUploadUrlRoot { get; set; } } } diff --git a/modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/Files/FileAppService.cs b/modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/Files/FileAppService.cs index 8f18608080..d8b9273f0c 100644 --- a/modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/Files/FileAppService.cs +++ b/modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/Files/FileAppService.cs @@ -1,5 +1,4 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.IO; using System.Threading.Tasks; @@ -20,7 +19,21 @@ namespace Volo.Blogging.Files Options = options.Value; } - public virtual Task UploadAsync(FileUploadInputDto input) + public virtual Task GetAsync(string name) + { + Check.NotNullOrWhiteSpace(name, nameof(name)); + + var filePath = Path.Combine(Options.FileUploadLocalFolder, name); + + return Task.FromResult( + new RawFileDto + { + Bytes = File.ReadAllBytes(filePath) + } + ); + } + + public virtual Task CreateAsync(FileUploadInputDto input) { if (input.Bytes.IsNullOrEmpty()) { @@ -44,7 +57,8 @@ namespace Volo.Blogging.Files return Task.FromResult(new FileUploadOutputDto { - Url = Options.FileUploadUrlRoot.EnsureEndsWith('/') + uniqueFileName + Name = uniqueFileName, + WebUrl = "/api/blogging/files/www/" + uniqueFileName }); } diff --git a/modules/blogging/src/Volo.Blogging.HttpApi/Volo/Blogging/BlogFilesController.cs b/modules/blogging/src/Volo.Blogging.HttpApi/Volo/Blogging/BlogFilesController.cs index 48f15e8657..818435a78c 100644 --- a/modules/blogging/src/Volo.Blogging.HttpApi/Volo/Blogging/BlogFilesController.cs +++ b/modules/blogging/src/Volo.Blogging.HttpApi/Volo/Blogging/BlogFilesController.cs @@ -1,7 +1,11 @@ -using System.Threading.Tasks; +using System.IO; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Volo.Abp; using Volo.Abp.AspNetCore.Mvc; +using Volo.Abp.Http; +using Volo.Blogging.Areas.Blog.Models; using Volo.Blogging.Files; namespace Volo.Blogging @@ -18,10 +22,60 @@ namespace Volo.Blogging _fileAppService = fileAppService; } + [HttpGet] + [Route("{name}")] + public Task GetAsync(string name) //TODO: output cache would be good + { + return _fileAppService.GetAsync(name); + } + + [HttpGet] + [Route("www/{name}")] + public async Task GetForWebAsync(string name) //TODO: output cache would be good + { + var file = await _fileAppService.GetAsync(name); + return File( + file.Bytes, + MimeTypes.GetByExtension(Path.GetExtension(name)) + ); + } + [HttpPost] - public Task UploadAsync(FileUploadInputDto input) + public Task CreateAsync(FileUploadInputDto input) { - return _fileAppService.UploadAsync(input); + return _fileAppService.CreateAsync(input); + } + + [HttpPost] + [Route("images/upload")] + public async Task UploadImage(IFormFile file) + { + //TODO: localize exception messages + + if (file == null) + { + throw new UserFriendlyException("No file found!"); + } + + if (file.Length <= 0) + { + throw new UserFriendlyException("File is empty!"); + } + + if (!file.ContentType.Contains("image")) + { + throw new UserFriendlyException("Not a valid image!"); + } + + var output = await _fileAppService.CreateAsync( + new FileUploadInputDto + { + Bytes = file.GetAllBytes(), + Name = file.FileName + } + ); + + return Json(new FileUploadResult(output.WebUrl)); } } } diff --git a/modules/blogging/src/Volo.Blogging.Web/Areas/Blog/Models/FileUploadResult.cs b/modules/blogging/src/Volo.Blogging.HttpApi/Volo/Blogging/FileUploadResult.cs similarity index 100% rename from modules/blogging/src/Volo.Blogging.Web/Areas/Blog/Models/FileUploadResult.cs rename to modules/blogging/src/Volo.Blogging.HttpApi/Volo/Blogging/FileUploadResult.cs diff --git a/modules/blogging/src/Volo.Blogging.Web/Areas/Blog/Controllers/FilesController.cs b/modules/blogging/src/Volo.Blogging.Web/Areas/Blog/Controllers/FilesController.cs deleted file mode 100644 index 7d3e12f3cd..0000000000 --- a/modules/blogging/src/Volo.Blogging.Web/Areas/Blog/Controllers/FilesController.cs +++ /dev/null @@ -1,55 +0,0 @@ -using System.Threading.Tasks; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc; -using Volo.Abp; -using Volo.Abp.AspNetCore.Mvc; -using Volo.Blogging.Areas.Blog.Models; -using Volo.Blogging.Files; -using Volo.Blogging.Hosting; - -namespace Volo.Blogging.Areas.Blog.Controllers -{ - //TODO: This may be moved to HttpApi project since it may be needed by a SPA too. - [Area("Blog")] - [Route("Blog/[controller]/[action]")] - public class FilesController : AbpController - { - private readonly IFileAppService _fileAppService; - - public FilesController(IFileAppService fileAppService) - { - _fileAppService = fileAppService; - } - - [HttpPost] - public async Task UploadImage(IFormFile file) - { - //TODO: localize exception messages - - if (file == null) - { - throw new UserFriendlyException("No file found!"); - } - - if (file.Length <= 0) - { - throw new UserFriendlyException("File is empty!"); - } - - if (!file.ContentType.Contains("image")) - { - throw new UserFriendlyException("Not a valid image!"); - } - - var output = await _fileAppService.UploadAsync( - new FileUploadInputDto - { - Bytes = file.AsBytes(), - Name = file.FileName - } - ); - - return Json(new FileUploadResult(output.Url)); - } - } -} \ No newline at end of file diff --git a/modules/blogging/src/Volo.Blogging.Web/Hosting/FormFileExtensions.cs b/modules/blogging/src/Volo.Blogging.Web/Hosting/FormFileExtensions.cs deleted file mode 100644 index aab0832bbf..0000000000 --- a/modules/blogging/src/Volo.Blogging.Web/Hosting/FormFileExtensions.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System.IO; -using JetBrains.Annotations; -using Microsoft.AspNetCore.Http; -using Volo.Abp; - -namespace Volo.Blogging.Hosting -{ - public static class FormFileExtensions - { - public static byte[] AsBytes(this IFormFile file) //TODO: Move to the framework (rename to GetBytes) - { - using (var stream = file.OpenReadStream()) - { - return stream.GetAllBytes(); - } - } - - public static void ValidateImage([CanBeNull] this IFormFile file) - { - - } - } -} \ No newline at end of file diff --git a/modules/blogging/src/Volo.Blogging.Web/Pages/Blog/Posts/edit.js b/modules/blogging/src/Volo.Blogging.Web/Pages/Blog/Posts/edit.js index 32bd7873ca..9fb4929d30 100644 --- a/modules/blogging/src/Volo.Blogging.Web/Pages/Blog/Posts/edit.js +++ b/modules/blogging/src/Volo.Blogging.Web/Pages/Blog/Posts/edit.js @@ -17,7 +17,7 @@ $.ajax({ type: "POST", - url: "/Blog/Files/UploadImage", + url: "/api/blogging/files/images/upload", data: formData, contentType: false, processData: false, @@ -42,7 +42,7 @@ $.ajax({ type: "POST", - url: "/Blog/Files/UploadImage", + url: "/api/blogging/files/images/upload", data: formData, contentType: false, processData: false, diff --git a/modules/blogging/src/Volo.Blogging.Web/Pages/Blog/Posts/new.js b/modules/blogging/src/Volo.Blogging.Web/Pages/Blog/Posts/new.js index f28cb48d44..519d3f41f4 100644 --- a/modules/blogging/src/Volo.Blogging.Web/Pages/Blog/Posts/new.js +++ b/modules/blogging/src/Volo.Blogging.Web/Pages/Blog/Posts/new.js @@ -19,7 +19,7 @@ $.ajax({ type: "POST", - url: "/Blog/Files/UploadImage", + url: "/api/blogging/files/images/upload", data: formData, contentType: false, processData: false, @@ -43,7 +43,7 @@ $.ajax({ type: "POST", - url: "/Blog/Files/UploadImage", + url: "/api/blogging/files/images/upload", data: formData, contentType: false, processData: false, diff --git a/samples/MicroserviceDemo/microservices/BloggingService.Host/BloggingServiceHostModule.cs b/samples/MicroserviceDemo/microservices/BloggingService.Host/BloggingServiceHostModule.cs index da076cf6e0..ac7af17fd4 100644 --- a/samples/MicroserviceDemo/microservices/BloggingService.Host/BloggingServiceHostModule.cs +++ b/samples/MicroserviceDemo/microservices/BloggingService.Host/BloggingServiceHostModule.cs @@ -85,7 +85,6 @@ namespace BloggingService.Host Configure(options => { options.FileUploadLocalFolder = Path.Combine(hostingEnvironment.WebRootPath, "files"); - options.FileUploadUrlRoot = "/files/"; }); context.Services.AddDistributedRedisCache(options => diff --git a/samples/MicroserviceDemo/microservices/BloggingService.Host/wwwroot/files/100d4c0445cbf55f687339ec8e656abb.jpg b/samples/MicroserviceDemo/microservices/BloggingService.Host/wwwroot/files/100d4c0445cbf55f687339ec8e656abb.jpg new file mode 100644 index 0000000000..5ff55ea887 Binary files /dev/null and b/samples/MicroserviceDemo/microservices/BloggingService.Host/wwwroot/files/100d4c0445cbf55f687339ec8e656abb.jpg differ diff --git a/samples/MicroserviceDemo/applications/PublicWebSite.Host/wwwroot/files/90974f3f1edb4ab0a10cf9759fd5f9ae.png b/samples/MicroserviceDemo/microservices/BloggingService.Host/wwwroot/files/90974f3f1edb4ab0a10cf9759fd5f9ae.png similarity index 100% rename from samples/MicroserviceDemo/applications/PublicWebSite.Host/wwwroot/files/90974f3f1edb4ab0a10cf9759fd5f9ae.png rename to samples/MicroserviceDemo/microservices/BloggingService.Host/wwwroot/files/90974f3f1edb4ab0a10cf9759fd5f9ae.png diff --git a/samples/MicroserviceDemo/applications/PublicWebSite.Host/wwwroot/files/ec882345a403be325bc539ebda211e79.jpg b/samples/MicroserviceDemo/microservices/BloggingService.Host/wwwroot/files/ec882345a403be325bc539ebda211e79.jpg similarity index 100% rename from samples/MicroserviceDemo/applications/PublicWebSite.Host/wwwroot/files/ec882345a403be325bc539ebda211e79.jpg rename to samples/MicroserviceDemo/microservices/BloggingService.Host/wwwroot/files/ec882345a403be325bc539ebda211e79.jpg