Included feedback
This commit is contained in:
@@ -1,10 +0,0 @@
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.eShopWeb.ApplicationCore.Interfaces
|
||||
{
|
||||
public interface IFileSystem
|
||||
{
|
||||
Task<bool> SavePicture(string pictureName, string pictureBase64, CancellationToken cancellationToken);
|
||||
}
|
||||
}
|
||||
@@ -7,11 +7,11 @@ namespace Microsoft.eShopWeb.ApplicationCore.Specifications
|
||||
{
|
||||
public CatalogFilterPaginatedSpecification(int skip, int take, int? brandId, int? typeId)
|
||||
: base()
|
||||
{
|
||||
{
|
||||
Query
|
||||
.Where(i => (!brandId.HasValue || i.CatalogBrandId == brandId) &&
|
||||
(!typeId.HasValue || i.CatalogTypeId == typeId))
|
||||
.Paginate(skip, take);
|
||||
.Skip(skip).Take(take);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,23 +80,7 @@
|
||||
<InputNumber @bind-Value="_item.Price" class="form-control" />
|
||||
<ValidationMessage For="(() => _item.Price)" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@*<div class="form-group">
|
||||
<label class="control-label col-md-6">@_item.PictureName</label>
|
||||
<div class="row">
|
||||
<div class="col-md-6 esh-form-information">
|
||||
<BlazorInputFile.InputFile OnChange="AddFile"/>
|
||||
</div>
|
||||
<div class="col-md-6 esh-form-information">
|
||||
@if (HasPicture)
|
||||
{
|
||||
<button type="button" class="btn btn-danger" @onclick="RemoveImage">Remove Picture</button>
|
||||
}
|
||||
</div>
|
||||
<span class="col-md-12" style="color: red;"> @_badFileMessage </span>
|
||||
</div>
|
||||
</div>*@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -171,26 +155,4 @@
|
||||
_modalClass = "";
|
||||
_showCreateModal = false;
|
||||
}
|
||||
|
||||
private async Task AddFile(IFileListEntry[] files)
|
||||
{
|
||||
_badFileMessage = string.Empty;
|
||||
|
||||
var file = files.FirstOrDefault();
|
||||
_item.PictureName = file?.Name;
|
||||
_item.PictureBase64 = await CatalogItem.DataToBase64(file);
|
||||
|
||||
_badFileMessage = CatalogItem.IsValidImage(_item.PictureName, _item.PictureBase64);
|
||||
if (!string.IsNullOrEmpty(_badFileMessage))
|
||||
{
|
||||
_item.PictureName = null;
|
||||
_item.PictureBase64 = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void RemoveImage()
|
||||
{
|
||||
_item.PictureName = null;
|
||||
_item.PictureBase64 = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,23 +83,7 @@
|
||||
<InputNumber @bind-Value="_item.Price" class="form-control" />
|
||||
<ValidationMessage For="(() => _item.Price)" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@*<div class="form-group">
|
||||
<label class="control-label col-md-6">@_item.PictureName</label>
|
||||
<div class="row">
|
||||
<div class="col-md-6 esh-form-information">
|
||||
<BlazorInputFile.InputFile OnChange="ChangeFile" />
|
||||
</div>
|
||||
<div class="col-md-6 esh-form-information">
|
||||
@if (HasPicture)
|
||||
{
|
||||
<button type="button" class="btn btn-danger" @onclick="RemoveImage">Remove Picture</button>
|
||||
}
|
||||
</div>
|
||||
<span class="col-md-12" style="color: red;"> @_badFileMessage </span>
|
||||
</div>
|
||||
</div>*@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -170,27 +154,4 @@
|
||||
_modalClass = "";
|
||||
_showEditModal = false;
|
||||
}
|
||||
|
||||
private async Task ChangeFile(IFileListEntry[] files)
|
||||
{
|
||||
_badFileMessage = string.Empty;
|
||||
|
||||
var file = files.FirstOrDefault();
|
||||
_item.PictureName = file?.Name;
|
||||
_item.PictureBase64 = await CatalogItem.DataToBase64(file);
|
||||
|
||||
_badFileMessage = CatalogItem.IsValidImage(_item.PictureName, _item.PictureBase64);
|
||||
if (!string.IsNullOrEmpty(_badFileMessage))
|
||||
{
|
||||
_item.PictureName = null;
|
||||
_item.PictureBase64 = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void RemoveImage()
|
||||
{
|
||||
_item.PictureName = null;
|
||||
_item.PictureBase64 = null;
|
||||
_item.PictureUri = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,84 +0,0 @@
|
||||
using Microsoft.eShopWeb.ApplicationCore.Interfaces;
|
||||
using Microsoft.eShopWeb.Infrastructure.Data;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.eShopWeb.Infrastructure.Services
|
||||
{
|
||||
// This class never gets called. Modify it based on your need.
|
||||
|
||||
public class WebFileSystem : IFileSystem
|
||||
{
|
||||
private readonly HttpClient _httpClient;
|
||||
private readonly string _url;
|
||||
public const string AUTH_KEY = "<IMAGE_FILE_UPLOAD_API_KEY>";
|
||||
|
||||
public WebFileSystem(string url)
|
||||
{
|
||||
_url = url;
|
||||
_httpClient = new HttpClient();
|
||||
_httpClient.DefaultRequestHeaders.Add("auth-key", AUTH_KEY);
|
||||
}
|
||||
|
||||
public async Task<bool> SavePicture(string pictureName, string pictureBase64, CancellationToken cancellationToken)
|
||||
{
|
||||
if (string.IsNullOrEmpty(pictureBase64) || !await UploadFile(pictureName, Convert.FromBase64String(pictureBase64), cancellationToken))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private async Task<bool> UploadFile(string fileName, byte[] fileData, CancellationToken cancellationToken)
|
||||
{
|
||||
if (!fileData.IsValidImage(fileName))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return await UploadToWeb(fileName, fileData, cancellationToken);
|
||||
}
|
||||
|
||||
private async Task<bool> UploadToWeb(string fileName, byte[] fileData, CancellationToken cancellationToken)
|
||||
{
|
||||
var request = new FileItem
|
||||
{
|
||||
DataBase64 = Convert.ToBase64String(fileData),
|
||||
FileName = fileName
|
||||
};
|
||||
|
||||
var content = new StringContent(JsonSerializer.Serialize(request), Encoding.UTF8, "application/json");
|
||||
|
||||
// TODO: Write the actual File image upload logic to web.
|
||||
// Post this image binary content to an Image Upload API.
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public static class ImageValidators
|
||||
{
|
||||
private const int ImageMaximumBytes = 512000;
|
||||
|
||||
public static bool IsValidImage(this byte[] postedFile, string fileName)
|
||||
{
|
||||
return postedFile != null && postedFile.Length > 0 && postedFile.Length <= ImageMaximumBytes && IsExtensionValid(fileName);
|
||||
}
|
||||
|
||||
private static bool IsExtensionValid(string fileName)
|
||||
{
|
||||
var extension = Path.GetExtension(fileName);
|
||||
|
||||
return string.Equals(extension, ".jpg", StringComparison.OrdinalIgnoreCase) ||
|
||||
string.Equals(extension, ".png", StringComparison.OrdinalIgnoreCase) ||
|
||||
string.Equals(extension, ".gif", StringComparison.OrdinalIgnoreCase) ||
|
||||
string.Equals(extension, ".jpeg", StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -43,11 +43,9 @@ namespace Microsoft.eShopWeb.PublicApi.CatalogItemEndpoints
|
||||
|
||||
if (newItem.Id != 0)
|
||||
{
|
||||
// At this point time, the Admin application uses the default catalog item image for any new product item.
|
||||
// But in the actual production scenario, you'll implement the image file upload mechanism in your application and set the image
|
||||
// file the Uri accordingly. You can refer to fewlines of the boilerplate code are commented out and kept it in the following files.
|
||||
// - BlazorAdmin project -> Create.razor and Edit.razor.
|
||||
// - Infrastructure project -> Services/WebFileSystem.cs
|
||||
//We disabled the upload functionality and added a default/placeholder image to this sample due to a potential security risk
|
||||
// pointed out by the community. More info in this issue: https://github.com/dotnet-architecture/eShopOnWeb/issues/537
|
||||
// In production, we recommend uploading to a blob storage and deliver the image via CDN after a verification process.
|
||||
|
||||
newItem.UpdatePictureUri("eCatalog-item-default.png");
|
||||
await _itemRepository.UpdateAsync(newItem, cancellationToken);
|
||||
|
||||
Reference in New Issue
Block a user