Skip to content

Commit 6b9af07

Browse files
authored
* simplcommerce#288 Adding Amazon S3 media storage
1 parent 164b1f7 commit 6b9af07

14 files changed

Lines changed: 225 additions & 80 deletions

File tree

SimplCommerce.sln

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SimplCommerce.Module.Pricin
6464
EndProject
6565
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SimplCommerce.Module.Tax", "src\Modules\SimplCommerce.Module.Tax\SimplCommerce.Module.Tax.csproj", "{78D8AEB4-BAE8-4671-9C89-482BE8CB58B7}"
6666
EndProject
67-
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SimplCommerce.Module.StorageLocal", "src\Modules\SimplCommerce.Module.StorageLocal\SimplCommerce.Module.StorageLocal.csproj", "{D399504C-4288-4692-A980-8265FA3A29AA}"
67+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SimplCommerce.Module.StorageLocal", "src\Modules\SimplCommerce.Module.StorageLocal\SimplCommerce.Module.StorageLocal.csproj", "{D399504C-4288-4692-A980-8265FA3A29AA}"
68+
EndProject
69+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SimplCommerce.Module.StorageAmazonS3", "src\Modules\SimplCommerce.Module.StorageAmazonS3\SimplCommerce.Module.StorageAmazonS3.csproj", "{6A4B7653-86A2-438B-B9FA-6A48E506A103}"
6870
EndProject
6971
Global
7072
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -364,6 +366,18 @@ Global
364366
{D399504C-4288-4692-A980-8265FA3A29AA}.Release|x64.Build.0 = Release|Any CPU
365367
{D399504C-4288-4692-A980-8265FA3A29AA}.Release|x86.ActiveCfg = Release|Any CPU
366368
{D399504C-4288-4692-A980-8265FA3A29AA}.Release|x86.Build.0 = Release|Any CPU
369+
{6A4B7653-86A2-438B-B9FA-6A48E506A103}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
370+
{6A4B7653-86A2-438B-B9FA-6A48E506A103}.Debug|Any CPU.Build.0 = Debug|Any CPU
371+
{6A4B7653-86A2-438B-B9FA-6A48E506A103}.Debug|x64.ActiveCfg = Debug|Any CPU
372+
{6A4B7653-86A2-438B-B9FA-6A48E506A103}.Debug|x64.Build.0 = Debug|Any CPU
373+
{6A4B7653-86A2-438B-B9FA-6A48E506A103}.Debug|x86.ActiveCfg = Debug|Any CPU
374+
{6A4B7653-86A2-438B-B9FA-6A48E506A103}.Debug|x86.Build.0 = Debug|Any CPU
375+
{6A4B7653-86A2-438B-B9FA-6A48E506A103}.Release|Any CPU.ActiveCfg = Release|Any CPU
376+
{6A4B7653-86A2-438B-B9FA-6A48E506A103}.Release|Any CPU.Build.0 = Release|Any CPU
377+
{6A4B7653-86A2-438B-B9FA-6A48E506A103}.Release|x64.ActiveCfg = Release|Any CPU
378+
{6A4B7653-86A2-438B-B9FA-6A48E506A103}.Release|x64.Build.0 = Release|Any CPU
379+
{6A4B7653-86A2-438B-B9FA-6A48E506A103}.Release|x86.ActiveCfg = Release|Any CPU
380+
{6A4B7653-86A2-438B-B9FA-6A48E506A103}.Release|x86.Build.0 = Release|Any CPU
367381
EndGlobalSection
368382
GlobalSection(SolutionProperties) = preSolution
369383
HideSolutionNode = FALSE
@@ -395,6 +409,7 @@ Global
395409
{D85B0F77-00A0-4090-994F-BA7643FDF522} = {7EFA2FA7-32DD-4047-B021-50E77A83D714}
396410
{78D8AEB4-BAE8-4671-9C89-482BE8CB58B7} = {7EFA2FA7-32DD-4047-B021-50E77A83D714}
397411
{D399504C-4288-4692-A980-8265FA3A29AA} = {7EFA2FA7-32DD-4047-B021-50E77A83D714}
412+
{6A4B7653-86A2-438B-B9FA-6A48E506A103} = {7EFA2FA7-32DD-4047-B021-50E77A83D714}
398413
EndGlobalSection
399414
GlobalSection(ExtensibilityGlobals) = postSolution
400415
SolutionGuid = {B9D0D8F0-1AB9-44DD-839F-ED8CEE7DDB10}

src/Modules/SimplCommerce.Module.Catalog/Controllers/CategoryApiController.cs

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ public IActionResult Get(long id)
6262

6363
[HttpPost]
6464
[Authorize(Roles = "admin")]
65-
public IActionResult Post(CategoryForm model)
65+
public async Task<IActionResult> Post(CategoryForm model)
6666
{
6767
if (ModelState.IsValid)
6868
{
@@ -77,22 +77,25 @@ public IActionResult Post(CategoryForm model)
7777
IsPublished = model.IsPublished
7878
};
7979

80-
SaveCategoryImage(category, model);
81-
80+
await SaveCategoryImage(category, model);
8281
_categoryService.Create(category);
83-
84-
return Ok();
82+
return CreatedAtAction(nameof(Get), new { id = category.Id }, null);
8583
}
86-
return new BadRequestObjectResult(ModelState);
84+
return BadRequest(ModelState);
8785
}
8886

8987
[HttpPut("{id}")]
9088
[Authorize(Roles = "admin")]
91-
public IActionResult Put(long id, CategoryForm model)
89+
public async Task<IActionResult> Put(long id, CategoryForm model)
9290
{
9391
if (ModelState.IsValid)
9492
{
95-
var category = _categoryRepository.Query().FirstOrDefault(x => x.Id == id);
93+
var category = await _categoryRepository.Query().FirstOrDefaultAsync(x => x.Id == id);
94+
if(category == null)
95+
{
96+
return NotFound();
97+
}
98+
9699
category.Name = model.Name;
97100
category.SeoTitle = model.Slug;
98101
category.Description = model.Description;
@@ -101,14 +104,14 @@ public IActionResult Put(long id, CategoryForm model)
101104
category.IncludeInMenu = model.IncludeInMenu;
102105
category.IsPublished = model.IsPublished;
103106

104-
SaveCategoryImage(category, model);
107+
await SaveCategoryImage(category, model);
105108

106109
_categoryService.Update(category);
107110

108-
return Ok();
111+
return Accepted();
109112
}
110113

111-
return new BadRequestObjectResult(ModelState);
114+
return BadRequest(ModelState);
112115
}
113116

114117
[HttpDelete("{id}")]
@@ -128,7 +131,7 @@ public async Task<IActionResult> Delete(long id)
128131

129132
await _categoryService.Delete(category);
130133

131-
return Ok();
134+
return NoContent();
132135
}
133136

134137
[HttpPost("{id}/products")]
@@ -178,11 +181,11 @@ public IActionResult UpdateProduct(long id, [FromBody] ProductCategoryForm model
178181
return Ok();
179182
}
180183

181-
private void SaveCategoryImage(Category category, CategoryForm model)
184+
private async Task SaveCategoryImage(Category category, CategoryForm model)
182185
{
183186
if (model.ThumbnailImage != null)
184187
{
185-
var fileName = SaveFile(model.ThumbnailImage);
188+
var fileName = await SaveFile(model.ThumbnailImage);
186189
if (category.ThumbnailImage != null)
187190
{
188191
category.ThumbnailImage.FileName = fileName;
@@ -194,11 +197,11 @@ private void SaveCategoryImage(Category category, CategoryForm model)
194197
}
195198
}
196199

197-
private string SaveFile(IFormFile file)
200+
private async Task<string> SaveFile(IFormFile file)
198201
{
199202
var originalFileName = ContentDispositionHeaderValue.Parse(file.ContentDisposition).FileName.Value.Trim('"');
200203
var fileName = $"{Guid.NewGuid()}{Path.GetExtension(originalFileName)}";
201-
_mediaService.SaveMedia(file.OpenReadStream(), fileName, file.ContentType);
204+
await _mediaService.SaveMediaAsync(file.OpenReadStream(), fileName, file.ContentType);
202205
return fileName;
203206
}
204207
}

src/Modules/SimplCommerce.Module.Catalog/Controllers/ProductApiController.cs

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -329,22 +329,21 @@ public async Task<IActionResult> Post(ProductForm model)
329329
product.AddCategory(productCategory);
330330
}
331331

332-
SaveProductMedias(model, product);
332+
await SaveProductMedias(model, product);
333333

334334
MapProductVariationVmToProduct(model, product);
335335
MapProductLinkVmToProduct(model, product);
336336

337337
_productService.Create(product);
338-
339-
return Ok();
338+
return CreatedAtAction(nameof(Get), new { id = product.Id }, null);
340339
}
341340

342341
[HttpPut("{id}")]
343342
public async Task<IActionResult> Put(long id, ProductForm model)
344343
{
345344
if (!ModelState.IsValid)
346345
{
347-
return new BadRequestObjectResult(ModelState);
346+
return BadRequest(ModelState);
348347
}
349348

350349
var product = _productRepository.Query()
@@ -356,6 +355,11 @@ public async Task<IActionResult> Put(long id, ProductForm model)
356355
.Include(x => x.Categories)
357356
.FirstOrDefault(x => x.Id == id);
358357

358+
if(product == null)
359+
{
360+
return NotFound();
361+
}
362+
359363
var currentUser = await _workContext.GetCurrentUser();
360364
if (!User.IsInRole("admin") && product.VendorId != currentUser.VendorId)
361365
{
@@ -389,12 +393,12 @@ public async Task<IActionResult> Put(long id, ProductForm model)
389393
product.StockQuantity = null;
390394
}
391395

392-
SaveProductMedias(model, product);
396+
await SaveProductMedias(model, product);
393397

394398
foreach (var productMediaId in model.Product.DeletedMediaIds)
395399
{
396400
var productMedia = product.Medias.First(x => x.Id == productMediaId);
397-
_mediaService.DeleteMedia(productMedia.Media);
401+
await _mediaService.DeleteMediaAsync(productMedia.Media);
398402
product.RemoveMedia(productMedia);
399403
}
400404

@@ -406,7 +410,7 @@ public async Task<IActionResult> Put(long id, ProductForm model)
406410

407411
_productService.Update(product);
408412

409-
return Ok();
413+
return Accepted();
410414
}
411415

412416
[HttpPost("change-status/{id}")]
@@ -421,13 +425,13 @@ public async Task<IActionResult> ChangeStatus(long id)
421425
var currentUser = await _workContext.GetCurrentUser();
422426
if (!User.IsInRole("admin") && product.VendorId != currentUser.VendorId)
423427
{
424-
return new BadRequestObjectResult(new { error = "You don't have permission to manage this product" });
428+
return BadRequest(new { error = "You don't have permission to manage this product" });
425429
}
426430

427431
product.IsPublished = !product.IsPublished;
428-
_productRepository.SaveChanges();
432+
await _productRepository.SaveChangesAsync();
429433

430-
return Ok();
434+
return Accepted();
431435
}
432436

433437
[HttpDelete("{id}")]
@@ -447,7 +451,7 @@ public async Task<IActionResult> Delete(long id)
447451

448452
await _productService.Delete(product);
449453

450-
return Ok();
454+
return NoContent();
451455
}
452456

453457
private static void MapProductVariationVmToProduct(ProductForm model, Product product)
@@ -712,11 +716,11 @@ private void AddOrDeleteProductAttribute(ProductForm model, Product product)
712716
}
713717
}
714718

715-
private void SaveProductMedias(ProductForm model, Product product)
719+
private async Task SaveProductMedias(ProductForm model, Product product)
716720
{
717721
if (model.ThumbnailImage != null)
718722
{
719-
var fileName = SaveFile(model.ThumbnailImage);
723+
var fileName = await SaveFile(model.ThumbnailImage);
720724
if (product.ThumbnailImage != null)
721725
{
722726
product.ThumbnailImage.FileName = fileName;
@@ -742,7 +746,7 @@ private void SaveProductMedias(ProductForm model, Product product)
742746

743747
foreach (var file in model.ProductImages)
744748
{
745-
var fileName = SaveFile(file);
749+
var fileName = await SaveFile(file);
746750
var productMedia = new ProductMedia
747751
{
748752
Product = product,
@@ -753,7 +757,7 @@ private void SaveProductMedias(ProductForm model, Product product)
753757

754758
foreach (var file in model.ProductDocuments)
755759
{
756-
var fileName = SaveFile(file);
760+
var fileName = await SaveFile(file);
757761
var productMedia = new ProductMedia
758762
{
759763
Product = product,
@@ -763,11 +767,11 @@ private void SaveProductMedias(ProductForm model, Product product)
763767
}
764768
}
765769

766-
private string SaveFile(IFormFile file)
770+
private async Task<string> SaveFile(IFormFile file)
767771
{
768772
var originalFileName = ContentDispositionHeaderValue.Parse(file.ContentDisposition).FileName.Value.Trim('"');
769773
var fileName = $"{Guid.NewGuid()}{Path.GetExtension(originalFileName)}";
770-
_mediaService.SaveMedia(file.OpenReadStream(), fileName, file.ContentType);
774+
await _mediaService.SaveMediaAsync(file.OpenReadStream(), fileName, file.ContentType);
771775
return fileName;
772776
}
773777
}

src/Modules/SimplCommerce.Module.Cms/Controllers/CarouselWidgetApiController.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ public async Task<IActionResult> Post(IFormCollection formCollection)
6060
{
6161
foreach (var item in model.Items)
6262
{
63-
item.Image = SaveFile(item.UploadImage);
63+
item.Image = await SaveFile(item.UploadImage);
6464
}
6565

6666
var widgetInstance = new WidgetInstance
@@ -91,9 +91,9 @@ public async Task<IActionResult> Put(long id, IFormCollection formCollection)
9191
{
9292
if (!string.IsNullOrWhiteSpace(item.Image))
9393
{
94-
_mediaService.DeleteMedia(item.Image);
94+
await _mediaService.DeleteMediaAsync(item.Image);
9595
}
96-
item.Image = SaveFile(item.UploadImage);
96+
item.Image = await SaveFile(item.UploadImage);
9797
}
9898
}
9999

@@ -149,11 +149,11 @@ private CarouselWidgetForm ToCarouselWidgetFormModel(IFormCollection formCollect
149149
return model;
150150
}
151151

152-
private string SaveFile(IFormFile file)
152+
private async Task<string> SaveFile(IFormFile file)
153153
{
154154
var originalFileName = ContentDispositionHeaderValue.Parse(file.ContentDisposition).FileName.Value.Trim('"');
155155
var fileName = $"{Guid.NewGuid()}{Path.GetExtension(originalFileName)}";
156-
_mediaService.SaveMedia(file.OpenReadStream(), fileName, file.ContentType);
156+
await _mediaService.SaveMediaAsync(file.OpenReadStream(), fileName, file.ContentType);
157157
return fileName;
158158
}
159159
}
Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.IO;
3+
using System.Threading.Tasks;
34
using Microsoft.AspNetCore.Authorization;
45
using Microsoft.AspNetCore.Http;
56
using Microsoft.AspNetCore.Mvc;
@@ -12,21 +13,21 @@ namespace SimplCommerce.Module.Core.Controllers
1213
[Route("api/common")]
1314
public class CommonApiController : Controller
1415
{
15-
private readonly IMediaService mediaService;
16+
private readonly IMediaService _mediaService;
1617

1718
public CommonApiController(IMediaService mediaService)
1819
{
19-
this.mediaService = mediaService;
20+
_mediaService = mediaService;
2021
}
2122

2223
[HttpPost("upload")]
23-
public IActionResult UploadFile(IFormFile file)
24+
public async Task<IActionResult> UploadFile(IFormFile file)
2425
{
2526
var originalFileName = ContentDispositionHeaderValue.Parse(file.ContentDisposition).FileName.Value.Trim('"');
2627
var fileName = $"{Guid.NewGuid()}{Path.GetExtension(originalFileName)}";
27-
mediaService.SaveMedia(file.OpenReadStream(), fileName, file.ContentType);
28+
await _mediaService.SaveMediaAsync(file.OpenReadStream(), fileName, file.ContentType);
2829

29-
return Ok(mediaService.GetMediaUrl(fileName));
30+
return Ok(_mediaService.GetMediaUrl(fileName));
3031
}
3132
}
3233
}

src/Modules/SimplCommerce.Module.Core/Services/IMediaService.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.IO;
2+
using System.Threading.Tasks;
23
using SimplCommerce.Module.Core.Models;
34

45
namespace SimplCommerce.Module.Core.Services
@@ -11,10 +12,10 @@ public interface IMediaService
1112

1213
string GetThumbnailUrl(Media media);
1314

14-
void SaveMedia(Stream mediaBinaryStream, string fileName, string mimeType = null);
15+
Task SaveMediaAsync(Stream mediaBinaryStream, string fileName, string mimeType = null);
1516

16-
void DeleteMedia(Media media);
17+
Task DeleteMediaAsync(Media media);
1718

18-
void DeleteMedia(string fileName);
19+
Task DeleteMediaAsync(string fileName);
1920
}
2021
}

0 commit comments

Comments
 (0)