Tewr.Blazor.FileReader - File Name - blazor-server-side

I am currently using the following to upload the files selected. However, I would like to use the file name of the local file for the server file name. I have not been able to discover how to recover that name.
public async Task ReadFile()
{
foreach (var file in await fileReaderService.CreateReference(inputTypeFileElement).EnumerateFilesAsync())
{
// Read into buffer and act (uses less memory)
await using (Stream stream = await file.OpenReadAsync())
{
buffer = new Byte[stream.Length];
// Do (async) stuff with stream...
await stream.ReadAsync(buffer);
}
// Read file fully into memory and act
using (MemoryStream memoryStream = await file.CreateMemoryStreamAsync(4096))
{
// Sync calls are ok once file is in memory
memoryStream.Read(buffer);
docManager.WriteImageToFile(memoryStream, upLoadFileName, Season);
}
}
}
How can I get the local file name in code?

You can get it from the FileInfo using the following code inside your foreach-loop:
IFileInfo fileInfo = await file.ReadFileInfoAsync();
string fileName = fileInfo.Name;
string contentType = fileInfo.Type;

Related

Blazor Server: Attempting to take files from InputFile into an Email attachment

I am currently trying to get the files received from InputFile and attach it as an email attachment. I followed this website to get my InputFile with the progress bar: https://www.meziantou.net/file-upload-with-progress-bar-in-blazor.htm.
I have tried various options such as converting the file to byte array, using memory stream, and using a file stream but I do not have a path to copy the file too. Here's my code currently on what I am trying to accomplish. The Email is sent through SMTP client and that works perfectly without the attachments.
private async ValueTask LoadFiles(InputFileChangeEventArgs e)
{
var files = e.GetMultipleFiles(maximumFileCount: 100);
filesList = e.GetMultipleFiles(maximumFileCount: 100);
var startIndex = uploadedFiles.Count;
// Add all files to the UI
foreach (var file in files)
{
var progress = new FileUploadProgress(file.Name, file.Size);
uploadedFiles.Add(progress);
}
await using var timer = new Timer(_ => InvokeAsync(() => StateHasChanged()));
timer.Change(TimeSpan.FromMilliseconds(500), TimeSpan.FromMilliseconds(500));
// Upload files
byte[] buffer = System.Buffers.ArrayPool<byte>.Shared.Rent(4096);
try
{
foreach (var file in files)
{
MemoryStream ms = new MemoryStream();
using var stream = file.OpenReadStream(maxAllowedSize: 10 * 1024 * 1024);
while (await stream.ReadAsync(buffer) is int read && read > 0)
{
uploadedFiles[startIndex].UploadedBytes += read;
file.OpenReadStream().CopyTo(ms);
var fileBytes = ms.ToArray();
Attachment fileAttch = new Attachment(new MemoryStream(fileBytes), file.ContentType);
message.Attachments.Add(fileAttch);
var readData = buffer.AsMemory().Slice(0, read);
}
startIndex++;
}
}
finally
{
System.Buffers.ArrayPool<byte>.Shared.Return(buffer);
// Update the UI with the final progress
StateHasChanged();
}
}
When using the debugger, I noticed that the try block breaks whenever I try to copy the file into MemoryStream. I am not sure why. Any help or solutions would be greatly appreciated.
Thank you
I have tried copying the file/buffer into the memory stream but the try block breaks. I have tried to use file stream without success. I am either missing something I am unaware of or I am not implementing the code correctly.

AWS Lambda image/pdf upload to S3 is corrupted (asp.net core)

I have written a function that uploads a file in an s3 bucket. It works fine when I run my application locally.
But when I deploy the application in AWS Lambda, file upload is working properly but the file is being corrupted. The uploaded file size is a little bit higher than the actual file size.
txt file upload is working fine.
Here is my code
Guid guid = Guid.NewGuid();
string extension = System.IO.Path.GetExtension(logo.FileName);
var fileName = $"{guid}{extension}";
using (var ms = new System.IO.MemoryStream())
{
logo.CopyTo(ms);
ms.Position = 0;
System.IO.Stream stream = ms;
var client = new AmazonS3Client(AppConstants.S3AccessKey, AppConstants.S3SecretKey, Amazon.RegionEndpoint.USEast1);
PutObjectRequest putRequest = new PutObjectRequest
{
BucketName = AppConstants.S3Bucket,
Key = fileName,
InputStream = stream
};
PutObjectResponse response = await client.PutObjectAsync(putRequest);
}
I have configure API Gateway for binary data as well as change the LambdaEntryPoint with following code
RegisterResponseContentEncodingForContentType("multipart/form-data", ResponseContentEncoding.Base64);
Is there any other configuration that I missed?
I think you are not showing the full code you have written. I had the same issue yesterday.
I was using the System.Drawing.Image namespace to store the image and then I was resizing it. The problem with the System.Drawing.Image is that it is supported only on the Windows platform. That's why it was working from the local machine.
This is how I have solved this issue:
I had to install a third-party library called ImageSharp. The code is written below:
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Processing;
using SixLabors.ImageSharp.Formats.Png;
public class Function
{
public MemoryStream GetReducedImage(int width, int height, MemoryStream resourceImage)
{
try
{
using (var image = Image.Load(resourceImage))
{
image.Mutate(x => x.Resize(width, height));
var ms = new MemoryStream();
image.Save(ms, new PngEncoder());
ms.Position = 0;
return ms;
}
}
catch (Exception e)
{
return null;
}
}
}

How do you upload 260kb PDF file to Azure Blob Storage using ASP.NET and .NET based Controller?

I currently am trying to upload a pdf file of size 260kb with Swagger UI and it doesnt work. If I try to do the same thing with a small 50kb Word file it works.
My controller code is:
[HttpPost()]
public async Task<IActionResult> Upload(IFormFile file)
{
var name = SanitizeFilename(file.FileName);
if (String.IsNullOrWhiteSpace(name))
{
throw new ArgumentException();
}
using (Stream stream = file.OpenReadStream())
{
await storage.Save(stream, name);
}
return Accepted();
}
My AzureBlobStorage class's save method is:
public async Task<Task> Save(Stream fileStream, string name)
{
var blobContainer = await GetBlobContainerAsync();
CloudBlockBlob blockBlob = blobContainer.GetBlockBlobReference(name);
var task = blockBlob.UploadFromStreamAsync(fileStream);
var success = task.IsCompletedSuccessfully;
return task;
//return blockBlob.UploadFromStreamAsync(fileStream);
}
Here is some of the debug windows:
This is from the controller of the word document:
This is from the controller of the PDF document:
Notice the red/pink lettering which is different.
This is from the AzureBlobStorage save method - word document:
This is from the AzureBlobStorage save method - pdf document:
I have read the IFormFile might not do continuous streaming but how do I know if that is the issue? And if it is, what is the preferred approach?
I am not following your logic here:
public async Task<Task> Save(Stream fileStream, string name)
{
var blobContainer = await GetBlobContainerAsync();
CloudBlockBlob blockBlob = blobContainer.GetBlockBlobReference(name);
var task = blockBlob.UploadFromStreamAsync(fileStream);
var success = task.IsCompletedSuccessfully;
return task;
//return blockBlob.UploadFromStreamAsync(fileStream);
}
This is the way it should be written:
public async Task Save(Stream fileStream, string name)
{
var blobContainer = await GetBlobContainerAsync();
CloudBlockBlob blockBlob = blobContainer.GetBlockBlobReference(name);
await blockBlob.UploadFromStreamAsync(fileStream);
}
You want to await for the task to finish here before you return.
Returning Task<Task> is slightly unorthodox and doesn't make sense for what you want to do here.
Also, keep in mind, if your file is really large, Kestrel server could give up on the request. There is a timeout in the range of around 90 seconds to complete the request. So, if uploading the file takes longer than 90 seconds, the caller could receive an error (but the upload will still finish).
Typically you will dump the file to the disk, then return an Accepted to the caller. Then post the file to a background queue to upload the file. More information about that here.

how to read excel file in memory (without saving it in disk) and return its content dotnet core

Im working on a webApi using dotnet core that takes the excel file from IFormFile and reads its content.Iam following the article
https://levelup.gitconnected.com/reading-an-excel-file-using-an-asp-net-core-mvc-application-2693545577db which is doing the same thing except that the file here is present on the server and mine will be provided by user.
here is the code:
public IActionResult Test(IFormFile file)
{
List<UserModel> users = new List<UserModel>();
System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance);
using (var stream = System.IO.File.Open(file.FileName, FileMode.Open, FileAccess.Read))
{
using (var reader = ExcelReaderFactory.CreateReader(stream))
{
while (reader.Read()) //Each row of the file
{
users.Add(new UserModel
{
Name = reader.GetValue(0).ToString(),
Email = reader.GetValue(1).ToString(),
Phone = reader.GetValue(2).ToString()
});
}
}
}
return Ok(users);
}
}
When system.IO tries to open the file, it could not find the path as the path is not present. How it is possible to either get the file path (that would vary based on user selection of file)? are there any other ways to make it possible.
PS: I dont want to upload the file on the server first, then read it.
You're using the file.FileName property, which refers to the file name the browser send. It's good to know, but not a real file on the server yet. You have to use the CopyTo(Stream) Method to access the data:
public IActionResult Test(IFormFile file)
{
List<UserModel> users = new List<UserModel>();
System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance);
using (var stream = new MemoryStream())
{
file.CopyTo(stream);
stream.Position = 0;
using (var reader = ExcelReaderFactory.CreateReader(stream))
{
while (reader.Read()) //Each row of the file
{
users.Add(new UserModel{Name = reader.GetValue(0).ToString(), Email = reader.GetValue(1).ToString(), Phone = reader.GetValue(2).ToString()});
}
}
}
return Ok(users);
}
Reference

Nothing happen while downloading xml file from server in .Net Core

This method connect given path which has to be xml file and save xml file to somewhere in server. Finally, download xml file from server by calling _downloadFileFromServer method
public async Task SaveFiletoServer(int id, string nud_preparationValue, int nud_divideNumber, string saveConfigPath, string saveConfigName)
{
try
{
await tryToConnect(id, nud_preparationValue, nud_divideNumber);
ReadXml.Save(XDocument,saveConfigPath,saveConfigName, nud_divideNumber);
await _downloadFileFromServer(saveConfigPath, saveConfigName);
}
catch (System.Exception ex)
{
ViewBag.DownloadError = ex.Message;
}
}
this method is using by above method(Download xml file from server).
private async Task _downloadFileFromServer(string saveConfigPath, string saveConfigName)
{
var memory = new MemoryStream();
using (var stream = new FileStream(string.Concat(saveConfigPath,saveConfigName,".xml"), FileMode.Open))
{
stream.CopyTo(memory);
}
memory.Position = 0;
await Task.FromResult(File(memory, "application/xml",string.Concat(saveConfigName,".xml")));
}
If I directly call _downloadFileFromServer method, it works correctly.xml file is downloading. However, when I call SaveFiletoServer method, _downloadFileFromServer method doesn't work correctly. Xml file is not downloading. I don't understand what is wrong.
Problem solved by using html.actionlink instead of ajax in order to download xml file with SaveFiletoServer method