How to upload and read an excel file (.xlsx) in a blazor server project - asp.net-core

I have a blazor server project and I need to send an excel file with data to create objects of an entity. I have searched a lot and have not found anything that has worked for me. I believe my problem is accessing the file to then be able to do what I want.
In my blazor component i have:
<InputFile OnChange="#ImportExcelFile" accept=".xlsx" multiple="false"></InputFile>
#code {
async Task ImportExcelFile(InputFileChangeEventArgs e)
{
await EnrollmentService.CreateEnrollmentByExcel(e);
}
}
In my EnrollmentService.cs i need to read file.
If anyone can help me I would be very grateful.

I can already access my entered file, I was researching and found several ways but it didn't satisfy my requirements because they were trying to store the file in a folder, I just wanted to read the data and store it in memory, and I got this that helped me. Thanks.
async Task ImportExcelFile(InputFileChangeEventArgs e)
{
foreach (var file in e.GetMultipleFiles(1))
{
try
{
using (MemoryStream ms = new MemoryStream())
{
// copy data from file to memory stream
await file.OpenReadStream().CopyToAsync(ms);
// positions the cursor at the beginning of the memory stream
ms.Position = 0;
// create ExcelPackage from memory stream
ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
using (ExcelPackage package = new ExcelPackage(ms))
{
ExcelWorksheet ws = package.Workbook.Worksheets.FirstOrDefault();
int colCount = ws.Dimension.End.Column;
int rowCount = ws.Dimension.End.Row;
var s = ws.Cells[2, 2].Value;
// rest of the code here...
}
}
}
catch (Exception ex)
{
throw;
}
}
}

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 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

Sensenet: upload files through sensenet client API for version 6.5 is not working properly

I have installed SenseNet version 6.5 (Code from codeplex). Wanted to upload the files in content repositry using Sensenet Client API, unfortunately it is not working with bulk upload.
string [] fileEntries = Directory.GetFiles(#"C:\Users\conyna\Downloads\Chirag");
foreach (string fileName in fileEntries)
{
using (Stream fs = File.OpenRead(fileName))
{
string fn = Path.GetFileName(fileName);
Task<SenseNet.Client.Content> x = SenseNet.Client.Content.UploadAsync("/Root/Sites/Default_Site/workspaces/(apps)/DocumentLibrary", fn, fs);
}
}
There are two problems with the code above:
you have to 'await' for async methods. Currently you start the task with the UploadAsync method, but you do not wait for it to finish, which casuses problems, because the file stream closes immediately after starting the upload task. Please upload files in an async way (of course you'll have to make your caller method async too, but that is the point of using an async api):
await Content.UploadAsync(...)
You may also consider using the Importer class in the client, it is able to import full directory structures.
You are trying to upload into an (apps) folder, which is not a correct target, that was designed to contain applications (mostly pages). It would be better if you uploaded into a document library in a workspace, for example:
/Root/Sites/Default_Site/workspaces/Document/SampleWorkspace/DocumentLibrary
We created a small application with SN ClientLibrary. I think, you can use this application/information/code.
This application can upload entire folders via Client Libray. Please check it out my Github repository: https://github.com/marosvolgyiz/SNClientLibraryUploader
There is relevant upload method:
public async Task Upload()
{
try
{
Console.WriteLine("Initilization...");
ClientContext.Initialize(new[] { sctx });
Console.WriteLine("Upload Started");
//Is Parent exists
var content = await Content.LoadAsync(Target);
if (content != null)
{
//Uploading files
var tasks = new List<Task>();
foreach (var file in Files)
{
string fileTargetFolder = Target + file.DirectoryName.Replace(Source, "").Replace(BaseDirectory, "").Replace("\\", "/");
var fileTargetContentFolder = await Content.LoadAsync(fileTargetFolder);
if (fileTargetContentFolder == null)
{
if (CreateFolderPath(Target, file.DirectoryName.Replace(Source, "")))
{
fileTargetContentFolder = await Content.LoadAsync(fileTargetFolder);
Console.WriteLine("#Upload file: " + file.FullName);
tasks.Add(Content.UploadAsync(fileTargetContentFolder.Id, file.Name, file.OpenRead()));
LoggerClass.LogToCSV("File uploaded", file.Name);
}
else
{
LoggerClass.LogToCSV("File target folder does not exist or you do not have enough permission to see! File can not be uploaded. ", file.Name);
}
}
else
{
Console.WriteLine("#Upload file: " + file.FullName);
tasks.Add(Content.UploadAsync(fileTargetContentFolder.Id, file.Name, file.OpenRead()));
LoggerClass.LogToCSV("File uploaded", file.Name);
}
}
await Task.WhenAll(tasks);
}
else
{
Console.WriteLine("Target does not exist or you do not have enough permission to see!");
LoggerClass.LogToCSV("Target does not exist or you do not have enough permission to see!");
}
Console.WriteLine("Upload finished.");
}
catch (Exception ex)
{
LoggerClass.LogToCSV(ex.Message);
}
}
I hope my answer is helpful to you.
Br,
maros