روش آپلود فایلها به همراه اطلاعات یک مدل در برنامههای Blazor WASM 5x
نویسنده: وحید نصیری
تاریخ: ۱۴۰۰/۰۲/۱۳ ۱۶:۴۵
آدرس: www.dntips.ir
| مطالب | ۳۶۹۴ |
| نویسندگان | ۲۷۶ |
| گروههای مطالب | ۱۰۲۴ |
| نقشههای راه | ۱۱۹ |
| دورهها | ۱۴ |
| اشتراکها | ۱۷۹۱۴ |
using System.ComponentModel.DataAnnotations;
namespace BlazorWasmUpload.Shared
{
public class User
{
[Required]
public string Name { get; set; }
[Required]
[Range(18, 90)]
public int Age { get; set; }
}
} namespace BlazorWasmUpload.Server.Controllers
{
[ApiController]
[Route("api/[controller]/[action]")]
public class FilesController : ControllerBase
{
[HttpPost]
public async Task<IActionResult> CreateUser(
[FromForm] User userModel,
[FromForm] IList<IFormFile> inputFiles = null) using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components.Forms;
namespace BlazorWasmUpload.Client.Services
{
public interface IFilesManagerService
{
Task<HttpResponseMessage> PostModelWithFilesAsync<T>(string requestUri,
IEnumerable<IBrowserFile> browserFiles,
string fileParameterName,
T model,
string modelParameterName);
}
public class FilesManagerService : IFilesManagerService
{
private readonly HttpClient _httpClient;
public FilesManagerService(HttpClient httpClient)
{
_httpClient = httpClient;
}
public async Task<HttpResponseMessage> PostModelWithFilesAsync<T>(
string requestUri,
IEnumerable<IBrowserFile> browserFiles,
string fileParameterName,
T model,
string modelParameterName)
{
var requestContent = new MultipartFormDataContent();
requestContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data");
if (browserFiles?.Any() == true)
{
foreach (var file in browserFiles)
{
var stream = file.OpenReadStream(maxAllowedSize: 512000 * 1000);
requestContent.Add(content: new StreamContent(stream, (int)file.Size), name: fileParameterName, fileName: file.Name);
}
}
requestContent.Add(
content: new StringContent(JsonSerializer.Serialize(model), Encoding.UTF8, "application/json"),
name: modelParameterName);
var result = await _httpClient.PostAsync(requestUri, requestContent);
result.EnsureSuccessStatusCode();
return result;
}
}
} namespace BlazorWasmUpload.Client
{
public class Program
{
public static async Task Main(string[] args)
{
var builder = WebAssemblyHostBuilder.CreateDefault(args);
// ...
builder.Services.AddScoped<IFilesManagerService, FilesManagerService>();
// ...
}
}
} @code
{
IReadOnlyList<IBrowserFile> SelectedFiles;
User UserModel = new User();
bool isProcessing;
string UploadErrorMessage; @page "/"
@using System.IO
@using BlazorWasmUpload.Shared
@using BlazorWasmUpload.Client.Services
@inject IFilesManagerService FilesManagerService
<h3>Post a model with files</h3>
<EditForm Model="UserModel" OnValidSubmit="CreateUserAsync">
<DataAnnotationsValidator />
<div>
<label>Name</label>
<InputText @bind-Value="UserModel.Name"></InputText>
<ValidationMessage For="()=>UserModel.Name"></ValidationMessage>
</div>
<div>
<label>Age</label>
<InputNumber @bind-Value="UserModel.Age"></InputNumber>
<ValidationMessage For="()=>UserModel.Age"></ValidationMessage>
</div>
<div>
<label>Photos</label>
<InputFile multiple disabled="@isProcessing" OnChange="OnInputFileChange" />
@if (!string.IsNullOrWhiteSpace(UploadErrorMessage))
{
<div>
@UploadErrorMessage
</div>
}
@if (SelectedFiles?.Count > 0)
{
<table>
<thead>
<tr>
<th>Name</th>
<th>Size (bytes)</th>
<th>Last Modified</th>
<th>Type</th>
</tr>
</thead>
<tbody>
@foreach (var selectedFile in SelectedFiles)
{
<tr>
<td>@selectedFile.Name</td>
<td>@selectedFile.Size</td>
<td>@selectedFile.LastModified</td>
<td>@selectedFile.ContentType</td>
</tr>
}
</tbody>
</table>
}
</div>
<div>
<button disabled="@isProcessing">Create user</button>
</div>
</EditForm> private void OnInputFileChange(InputFileChangeEventArgs args)
{
var files = args.GetMultipleFiles(maximumFileCount: 15);
if (args.FileCount == 0 || files.Count == 0)
{
UploadErrorMessage = "Please select a file.";
return;
}
var allowedExtensions = new List<string> { ".jpg", ".png", ".jpeg" };
if(!files.Any(file => allowedExtensions.Contains(Path.GetExtension(file.Name), StringComparer.OrdinalIgnoreCase)))
{
UploadErrorMessage = "Please select .jpg/.jpeg/.png files only.";
return;
}
SelectedFiles = files;
UploadErrorMessage = string.Empty;
} private async Task CreateUserAsync()
{
try
{
isProcessing = true;
await FilesManagerService.PostModelWithFilesAsync(
requestUri: "api/Files/CreateUser",
browserFiles: SelectedFiles,
fileParameterName: "inputFiles",
model: UserModel,
modelParameterName: "userModel");
UserModel = new User();
}
finally
{
isProcessing = false;
SelectedFiles = null;
}
} using System.IO;
using Microsoft.AspNetCore.Mvc;
using BlazorWasmUpload.Shared;
using Microsoft.AspNetCore.Hosting;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using System.Collections.Generic;
using Microsoft.Extensions.Logging;
using System.Text.Json;
using BlazorWasmUpload.Server.Utils;
using System.Linq;
namespace BlazorWasmUpload.Server.Controllers
{
[ApiController]
[Route("api/[controller]/[action]")]
public class FilesController : ControllerBase
{
private const int MaxBufferSize = 0x10000;
private readonly IWebHostEnvironment _webHostEnvironment;
private readonly ILogger<FilesController> _logger;
public FilesController(
IWebHostEnvironment webHostEnvironment,
ILogger<FilesController> logger)
{
_webHostEnvironment = webHostEnvironment;
_logger = logger;
}
[HttpPost]
public async Task<IActionResult> CreateUser(
//[FromForm] string userModel, // <-- this is the actual form of the posted model
[ModelBinder(BinderType = typeof(JsonModelBinder)), FromForm] User userModel,
[FromForm] IList<IFormFile> inputFiles = null)
{
/*var user = JsonSerializer.Deserialize<User>(userModel);
_logger.LogInformation($"userModel.Name: {user.Name}");
_logger.LogInformation($"userModel.Age: {user.Age}");*/
_logger.LogInformation($"userModel.Name: {userModel.Name}");
_logger.LogInformation($"userModel.Age: {userModel.Age}");
var uploadsRootFolder = Path.Combine(_webHostEnvironment.WebRootPath, "Files");
if (!Directory.Exists(uploadsRootFolder))
{
Directory.CreateDirectory(uploadsRootFolder);
}
if (inputFiles?.Any() == true)
{
foreach (var file in inputFiles)
{
if (file == null || file.Length == 0)
{
continue;
}
var filePath = Path.Combine(uploadsRootFolder, file.FileName);
using var fileStream = new FileStream(filePath,
FileMode.Create,
FileAccess.Write,
FileShare.None,
MaxBufferSize,
useAsync: true);
await file.CopyToAsync(fileStream);
_logger.LogInformation($"Saved file: {filePath}");
}
}
return Ok();
}
}
} [ModelBinder(BinderType = typeof(JsonModelBinder)), FromForm] User userModel,
using System;
using System.Text.Json;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.ModelBinding;
namespace BlazorWasmUpload.Server.Utils
{
public class JsonModelBinder : IModelBinder
{
public Task BindModelAsync(ModelBindingContext bindingContext)
{
if (bindingContext == null)
{
throw new ArgumentNullException(nameof(bindingContext));
}
var valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
if (valueProviderResult != ValueProviderResult.None)
{
bindingContext.ModelState.SetModelValue(bindingContext.ModelName, valueProviderResult);
var valueAsString = valueProviderResult.FirstValue;
var result = JsonSerializer.Deserialize(valueAsString, bindingContext.ModelType);
if (result != null)
{
bindingContext.Result = ModelBindingResult.Success(result);
return Task.CompletedTask;
}
}
return Task.CompletedTask;
}
}
} [HttpPost]
public async Task<IActionResult> CreateUser(
[FromForm] string userModel, // <-- this is the actual form of the posted model
[FromForm] IList<IFormFile> inputFiles = null)
{
var user = JsonSerializer.Deserialize<User>(userModel); [HttpGet]
[Route("GetImagess")]
public async Task<ActionResult> GetImagess ()
{
var rootPath = _webHostEnverioment.WebRootFileProvider.GetDirectoryContents("/_content/CommonComponents").FirstOrDefault(x => x.Name == "lib").PhysicalPath;
....
} bin\Debug\net6.0\publish\wwwroot\_content\MyComponentName\image.png
/_content/MyComponentName/image.png
return File("/_content/MyComponentName/image.png", "image/png", "image.png"); var dir = Path.Combine(_webHostEnvironment.WebRootPath, "_content", "MyLibName", "Folder1"); var files = Directory.GetFiles(dir, "*.*");
using var inputStream = inputFile.OpenReadStream(); using var memoryString = new MemoryStream(); await inputStream.CopyToAsync(memoryString); var base64 = Convert.ToBase64String(memoryString.ToArray());