I have setup a Blazor WebAssembly ASP.Net Core hosted PWA
project and am using Azure Cognitive Services
in it. Therefore I have in one of my client-views a form where the user can upload an image and this will be referred to Azure.
In the razor-view I have this:
@inject HttpClient client;
@inject IFileReaderService FileReader;
@inject NavigationManager navi;
<div class="text-center">
<input class="btn btn-secondary " name="file" @ref="InpReference" type="file" id="file-selector" placeholder="Brows" accept="image/*" capture="camera" @onclick="InputFile">
@if (_fileSelected != false)
{
<input class="btn btn-primary" type="button" role="button" id="startbutton" @onclick="Upload" value="upload" />
}
</div>
@code {
private async Task Upload()
{
// content base structure
MultipartFormDataContent content = new MultipartFormDataContent();
content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("form-data");
foreach (/*IFileReference*/var fileReference in fileReferences)
{
Console.WriteLine("test1");
// getting the file size
IFileInfo fileinfo = await fileReference.ReadFileInfoAsync();
Stream fileStream;
var fileReferencesArray = fileReferences.ToArray();
using (var fs = await fileReference.CreateMemoryStreamAsync((int)fileinfo.Size))
{
Console.WriteLine("test2");
fileStream=new MemoryStream(fs.ToArray());
}
Console.WriteLine("test4" + fileinfo.Size);
StreamContent sc = new StreamContent(fileStream, (int)fileStream.Length);
content.Add(sc, "file", fileinfo.Name);
Console.WriteLine("test5");
}
Console.WriteLine("test6");
var response = await client.PostJsonAsync<List<Prediction>>("api/Azure/Prediction", content);
Console.WriteLine(response.Count + " : " + response.GetType().ToString());
foreach (var prediction in response)
{
Console.WriteLine(prediction.Id + ":" + prediction.Name + "," + prediction.Probability.ToString());
}
navi.NavigateTo("detailView/");
}
}
My WebApi Controller for the handling:
...
[HttpPost]
public List<Prediction> getPrediction([FromForm]IFormFile file)
{
if (file == null)
{
return new List<Prediction>();
}
List<Prediction> predicitions = azure_Client.GetPrediction(file.OpenReadStream());
return predicitions;
}
...
The problem is that the [FromForm]IFormFile file
in the controller is always null
. This is only null in the PWA
project. I have set the same project up without PWA
and it works, it is not null
and it is getting the selected image from the view! What is the difference there and why isn't the HttpClient
doing the same as in the Blazor WebAssembly ASP.Net Core hosted
?
According to my test, if you want to upload file in Blazor WebAssembly ASP.Net Core hosted PWA, please refer to the following steps
Client(I use the sdk Tewr.Blazor.FileReader
)
a. update Program.cs
builder.Services.AddFileReaderService(options => {
options.UseWasmSharedBuffer = true;
});
builder.Services.AddTransient(sp =>
new HttpClient
{
BaseAddress = new Uri(builder.HostEnvironment.BaseAddress)
});
b. upload file razor-view
@using System.IO
@using Blazor.FileReader
@inject HttpClient client;
@inject IFileReaderService fileReader
<h1>File uplaod Blzaor WebAssembly!</h1>
<div class="row">
<div class="col-4">
<div class="form-group">
<input type="file" name="image" @ref="inputReference" @onchange="async() =>await OpenFile()" />
<ul>
<li>File Name: @fileName</li>
<li>Size: @size</li>
<li>Type: @type</li>
</ul>
</div>
<button class="btn btn-block btn-success" @onclick="async() =>await UploadFile()"> Upload File</button>
@if (!string.IsNullOrWhiteSpace(message))
{
<div class="alert alert-success">
File has been uplaoded
</div>
}
</div>
</div>
@code{
ElementReference inputReference;
string message = string.Empty;
string fileName = string.Empty;
string type = string.Empty;
string size = string.Empty;
Stream fileStream=null;
async Task UploadFile()
{
var content = new MultipartFormDataContent();
content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("form-data");
var sc = new StreamContent(fileStream, (int)fileStream.Length);
content.Add(sc, "image", fileName);
var response = await client.PostAsync("/upload", content);
if (response.IsSuccessStatusCode) {
message = "OK";
}
}
async Task OpenFile()
{
var file = (await fileReader.CreateReference(inputReference).EnumerateFilesAsync()).FirstOrDefault();
if (file == null) {
return;
}
var fileInfo=await file.ReadFileInfoAsync();
fileName = fileInfo.Name;
type = fileInfo.Type;
size = $"{fileInfo.Size} Bytes";
using (var ms = await file.CreateMemoryStreamAsync((int)fileInfo.Size)) {
fileStream = new MemoryStream(ms.ToArray());
}
}
}
API COntroller
[HttpPost]
public async Task<IActionResult> Post([FromForm(Name ="image")]IFormFile file) {
if (file == null || file.Length == 0) {
return BadRequest("do not receive file");
}
var fileName = file.FileName;
var extension = Path.GetExtension(fileName);
var newFileName = $"{Guid.NewGuid()}{extension}";
var filePath = Path.Combine(_env.ContentRootPath, "Images", newFileName);
if (!Directory.Exists(Path.Combine(_env.ContentRootPath, "Images"))) {
Directory.CreateDirectory(Path.Combine(_env.ContentRootPath, "Images"));
}
using (var stream = new FileStream(filePath, FileMode.Create, FileAccess.Write)) {
await file.CopyToAsync(stream);
}
return Ok(filePath);
}