Saving user-uploaded images in asp.net mvc - c#

I'm trying to post an uploaded image from the front-end using aurelia to a asp.net mvc. Is there someway I can save the image received in as png format in a folder on the server?
Javascript method from where I'm posting the image data(files is the uploaded image and id is the unique image ID that I need to use for the file name)
saveImage(files,id) {
var form = new FormData()
form.append('file', files)
form.append('ID', id)
this.http.fetch('/api/Employees', {
method: 'post',
body: form
})
return true;
}
ImagesController(Asp.net MVC)
using Microsoft.AspNetCore.Mvc;
using System;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
namespace SPAproject.Controllers
{
public class ImagesController : Controller
{
[HttpPost, Route("api/[controller]")]
public async Task<IActionResult> SaveImage()
{
try
{
var form = await Request.ReadFormAsync();
var file = form.Files.First();
var id = form.ElementAt(1);
var path = "/images/" + id + ".png";
Stream stream = file.OpenReadStream();
return Ok(true);
}
catch (Exception ex)
{
var originalMessage = ex.Message;
while (ex.InnerException != null)
ex = ex.InnerException;
return BadRequest($"{originalMessage} | {ex.Message}");
}
}
}
}
}

string fileName = string.Format("{0}{1}", id, ".png");
var serverPath = Server.MapPath("~/images");
var path = Path.Combine(serverPath, fileName);
using (Stream inputStream = file.OpenReadStream())
using (var outputStream = new FileStream(path, FileMode.Create))
{
// dump a stream to a file
inputStream.CopyTo(outputStream);
}

I assume you use ASP.NET Core, not ASP.NET(using Microsoft.AspNetCore.Mvc;)
You can use new class in asp.net core, IFormFile. It simplifies the stream operations.
[HttpPost("UploadFiles")]
public async Task<IActionResult> Post(List<IFormFile> files)
{
long size = files.Sum(f => f.Length);
// full path to file in temp location
var filePath = Path.GetTempFileName();
foreach (var formFile in files)
{
if (formFile.Length > 0)
{
using (var stream = new FileStream(filePath, FileMode.Create))
{
await formFile.CopyToAsync(stream);
}
}
}
// process uploaded files
// Don't rely on or trust the FileName property without validation.
return Ok(new { count = files.Count, size, filePath});
}
Also, you can find the full documentation here. File uploads in ASP.NET Core:

Related

Download multiple files .NET CORE Web API as ArchiveZip return root directory

I make a private class to get the bytes of the file and then return it into a zip file. Basically, I just want to pick specific files inside my folder and then zip it then download it. Here's my class:
private FileResult DownloadMultipleFiles(List<byte[]> byteArrayList)
{
var zipName = $"archive-EvidenceFiles-{DateTime.Now.ToString("yyyy_MM_dd-HH_mm_ss")}.zip";
using (MemoryStream ms = new MemoryStream())
{
using (var archive = new ZipArchive(ms, ZipArchiveMode.Create, true))
{
foreach (var file in byteArrayList)
{
string fPath = Encoding.ASCII.GetString(file);
var entry = archive.CreateEntry(fPath, CompressionLevel.Fastest);
using (var zipStream = entry.Open())
{
zipStream.Write(file, 0, file.Length);
}
}
}
return File(ms.ToArray(), "application/zip", zipName);
}
}
And then, here's my controller:
[HttpGet("GetBundleFiles/{rhaId}")]
public async Task<IActionResult> GetBundleFiles(string rhaId)
{
List<byte[]> filesPath = new List<byte[]>();
var results = await _rhaFileEvidence.GetByRhaID(rhaId);
var files = results.ToList();
if (files.Count == 0)
return Ok(new { status = "null", message = "Empty data" });
files.ForEach(file =>
{
var fPath = file.FilePath;
byte[] bytes = Encoding.ASCII.GetBytes(fPath);
filesPath.Add(bytes);
});
return DownloadMultipleFiles(filesPath);
}
The controller works well, I can download the zip but when I open it, I can't get the files instead I get the root directory of the project I saved, like D:. I think I make mistake when making the memory stream or something, is there any suggestion how can I fix this? (Paste some solution code in the answer please)
you are getting the directory root because when you use archive.CreateEntry you are passing the file full path in parameter, you should be using only the file name
var entry = archive.CreateEntry(System.IO.Path.GetFileName(fPath), CompressionLevel.Fastest);
a second issue is that you actually saving the file path to your files not the content of the original file. you can update your DownloadMultipleFiles like this
private FileResult DownloadMultipleFiles(List<byte[]> byteArrayList)
{
var zipName = $"archive-EvidenceFiles-{DateTime.Now.ToString("yyyy_MM_dd-HH_mm_ss")}.zip";
using (MemoryStream ms = new MemoryStream())
{
using (var archive = new ZipArchive(ms, ZipArchiveMode.Create, true))
{
foreach (var file in byteArrayList)
{
string fPath = Encoding.ASCII.GetString(file);
var entry = archive.CreateEntry(System.IO.Path.GetFileName(fPath), CompressionLevel.Fastest);
using (var zipStream = entry.Open())
{
var bytes = System.IO.File.ReadAllBytes(fPath);
zipStream.Write(bytes, 0, bytes.Length);
}
}
}
return File(ms.ToArray(), "application/zip", zipName);
}
}

"Compressed folder is invalid" error returning a zip file from a Web API endpoint

I'm trying to compress/zip a Json string to a file and return that file from my method.
When I try to open the resulting zip file I get a message about the "compressed folder is invalid"
public FileContentResult GenerateZip()
{
var jsonResult = JsonSerializer.Serialize(GenerateReport());
FileContentResult outputFile;
using (var uncompressedStream = new MemoryStream(Encoding.UTF8.GetBytes(jsonResult)))
{
using (var compressedStream = new MemoryStream())
{
using (var compressorStream = new DeflateStream(compressedStream, CompressionLevel.Fastest, true))
{
uncompressedStream.CopyTo(compressorStream);
}
outputFile = new FileContentResult(compressedStream.ToArray(), "application/zip")
{
FileDownloadName = "TestReport.Zip"
};
}
}
return outputFile;
}
The above method is called from a WebAPI endpoint.
[HttpGet]
public FileContentResult GetZip()
{
var file = new ReportsBLL(_context, _logger, _config).GenerateZip();
return File(file.FileContents, file.ContentType, file.FileDownloadName);
}
I've also tried the above code using GZipStream instead of DeflateStream.

How to download a png file with ASP.NET Core

I need the user to be able to download png images from my site. When the mthod runs it completes without errors but no image is downloaded. I do not need the user to see a pop-up dialog thought it is certainly helpful. This is what I have right now:
public async Task<IActionResult> DownloadImage(string filename)
{
var path = Path.GetFullPath("./wwwroot/images/school-assets/" + filename);
MemoryStream memory = new MemoryStream();
using (FileStream stream = new FileStream(path, FileMode.Open))
{
await stream.CopyToAsync(memory);
}
memory.Position = 0;
return File(memory, "image/png", "download");
}
This method is called by an ajax call in the view that looks like this
$.ajax({
url: "./MyHome/DownloadImage",
type: "Get",
data: {filename : filename},
success: function (file) {
},
error: function (request, status, error) {
console.log(request.responseText);
}
});
}
Edit:
If i console.log file in the success portion i see a string of bytes so I know it is creating the file but not letting the user get to i. I have tried content disposition and creating a physical file result as suggested.
For File, you need to provide the file name with file extension, otherwise, the downloaded file will not be able to open.
Try something like
public async Task<IActionResult> DownloadImage(string filename)
{
var path = Path.GetFullPath("./wwwroot/images/school-assets/" + filename);
MemoryStream memory = new MemoryStream();
using (FileStream stream = new FileStream(path, FileMode.Open))
{
await stream.CopyToAsync(memory);
}
memory.Position = 0;
return File(memory, "image/png", Path.GetFileName(path));
}
You need to set the content dispositon type to enable direct downloading of the file :
public IActionResult OnGetPng()
{
var bytes = System.IO.File.ReadAllBytes("test.png");
var cd = new System.Net.Mime.ContentDisposition
{
FileName = "test.png",
Inline = false
};
Response.Headers.Add("Content-Disposition", cd.ToString());
Response.Headers.Add("X-Content-Type-Options", "nosniff");
return File(bytes, "image/png");
}
If you prefer you can also make use of the PhysicalFileResult type which takes care of your stream and return FileResult from your controller. In that case your code looks like this:
var fn = Path.Combine(env.WebRootPath, "test.png");
var contentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment");
Response.Headers[HeaderNames.ContentDisposition] = contentDisposition.ToString();
return new PhysicalFileResult(fn, "image/jpeg");
To get access to the WebRootPath you have to inject IHostingEnvironment env into your constructor.
#Caleb sir from below code you can download png file.
Download png file from folder
[HttpGet]
public FileStreamResult DownloadPngFile(string fileName)
{
var stream = new FileStream(Directory.GetCurrentDirectory() + "\\wwwroot\\images\\school-assets\\" + fileName, FileMode.Open);
return new FileStreamResult(stream, "image/png");
}
Download png file from database
[HttpGet]
public FileStreamResult DownloadPngFileFromDataBase(string id)
{
var _fileUpload = _db.ImageFileUpload.SingleOrDefault(aa => aa.fileid == id);
// _fileUpload.FileContent column type is byte
MemoryStream ms = new MemoryStream(_fileUpload.FileContent);
return new FileStreamResult(ms, "image/png");
}
For more info please also see this question and answer. Download Pdf file in asp.net core (accepted answer) and one more extra link
Download files in asp.net core
This code can save photos from URL addresses in the server folder.
private readonly Lazy<HttpClient> _client;
In constructor:
_client = new Lazy<HttpClient>(() => clientFactory.CreateClient());
That is better to use lazy loading in a way the server will not spend additional resources to create HttpClient immediately.
public async Task<string> SavePhotoInFolder(string url)
{
string photoPath = $"/Photos/{Guid.NewGuid()}.jpeg";
using (var request = new HttpRequestMessage(HttpMethod.Get, url))
using (
Stream contentStream = await (await _client.Value.SendAsync(request)).Content.ReadAsStreamAsync(),
stream = new FileStream($"{_appEnvironment.WebRootPath}{photoPath}", FileMode.Create))
{
await contentStream.CopyToAsync(stream);
}
return photoPath;
}
You can use HttpClient
using (var client = new HttpClient())
{
try
{
using var result = await client.GetAsync($"http://{url}");
if (result.IsSuccessStatusCode)
{
return await result.Content.ReadAsByteArrayAsync();
}
}
catch(Exception ex)
{
Console.WriteLine(ex.InnerException);
}
}

ASP Core WebApi Test File Upload using Postman

I have created an endpoint that takes an arbitrary file:
[HttpPost()]
public async Task<IActionResult> CreateFile(IFormFile file)
When I test it with Postman, the file is always null.
Here is what I am doing in Postman:
What am I doing wrong?
Thanks to #rmjoia's comment I got it working! Here is what I had to do in Postman:
The complete solution for uploading file or files is shown below:
This action use for uploading multiple files:
// Of course this action exist in microsoft docs and you can read it.
HttpPost("UploadMultipleFiles")]
public async Task<IActionResult> Post(List<IFormFile> files)
{
long size = files.Sum(f => f.Length);
// Full path to file in temp location
var filePath = Path.GetTempFileName();
foreach (var formFile in files)
{
if (formFile.Length > 0)
using (var stream = new FileStream(filePath, FileMode.Create))
await formFile.CopyToAsync(stream);
}
// Process uploaded files
return Ok(new { count = files.Count, path = filePath});
}
The postman picture shows how you can send files to this endpoint for uploading multiple files:
This action use for uploading single file:
[HttpPost("UploadSingleFile")]
public async Task<IActionResult> Post(IFormFile file)
{
// Full path to file in temp location
var filePath = Path.GetTempFileName();
if (file.Length > 0)
using (var stream = new FileStream(filePath, FileMode.Create))
await file.CopyToAsync(stream);
// Process uploaded files
return Ok(new { count = 1, path = filePath});
}
The postman picture shows how you can send a file to this endpoint for uploading single file:
Your should be like that
[HttpPost]
public async Task<IActionResult> UploadFile([FromForm]UploadFile updateTenantRequest)
{
}
Your class should be like:-
public class UpdateTenantRequestdto
{
public IFormFile TenantLogo { get; set; }
}
and then
[HttpPost("UploadSingleFile"), Route("[action]")]
public async Task<IActionResult> UploadSingleFile([FromForm(Name = "file")] IFormFile file)
{
// Process uploaded files
string folderName = "Uploads";
string webRootPath = hostingEnvironment.WebRootPath;
string newPath = Path.Combine(webRootPath, folderName);
if (!Directory.Exists(newPath))
{
Directory.CreateDirectory(newPath);
}
Repository.Models.File fileModel = new Repository.Models.File();
fileModel.Name = ContentDispositionHeaderValue.Parse(file.ContentDisposition).FileName.Trim('"');
fileModel.Path = $"{folderName}/{file.FileName}";
fileModel.Size = file.Length;
fileModel.Type = file.ContentType;
string fullPath = Path.Combine(newPath, fileModel.Name);
fileModel.Extension = Path.GetExtension(fullPath);
fileModel.CreatedDate = Utility.Common.GetDate;
fileModel.CreatedBy = 1;
//fileModel save to db
using (var stream = new FileStream(fullPath, FileMode.Create))
{
//file.CopyTo(stream);
await file.CopyToAsync(stream);
}
return Ok(new { count = 1, path = filePath });
}

How To Accept a File POST

I'm using asp.net mvc 4 webapi beta to build a rest service. I need to be able to accept POSTed images/files from client applications. Is this possible using the webapi? Below is how action I am currently using. Does anyone know of an example how this should work?
[HttpPost]
public string ProfileImagePost(HttpPostedFile profileImage)
{
string[] extensions = { ".jpg", ".jpeg", ".gif", ".bmp", ".png" };
if (!extensions.Any(x => x.Equals(Path.GetExtension(profileImage.FileName.ToLower()), StringComparison.OrdinalIgnoreCase)))
{
throw new HttpResponseException("Invalid file type.", HttpStatusCode.BadRequest);
}
// Other code goes here
return "/path/to/image.png";
}
I'm surprised that a lot of you seem to want to save files on the server. Solution to keep everything in memory is as follows:
[HttpPost("api/upload")]
public async Task<IHttpActionResult> Upload()
{
if (!Request.Content.IsMimeMultipartContent())
throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
var provider = new MultipartMemoryStreamProvider();
await Request.Content.ReadAsMultipartAsync(provider);
foreach (var file in provider.Contents)
{
var filename = file.Headers.ContentDisposition.FileName.Trim('\"');
var buffer = await file.ReadAsByteArrayAsync();
//Do whatever you want with filename and its binary data.
}
return Ok();
}
see http://www.asp.net/web-api/overview/formats-and-model-binding/html-forms-and-multipart-mime#multipartmime, although I think the article makes it seem a bit more complicated than it really is.
Basically,
public Task<HttpResponseMessage> PostFile()
{
HttpRequestMessage request = this.Request;
if (!request.Content.IsMimeMultipartContent())
{
throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
}
string root = System.Web.HttpContext.Current.Server.MapPath("~/App_Data/uploads");
var provider = new MultipartFormDataStreamProvider(root);
var task = request.Content.ReadAsMultipartAsync(provider).
ContinueWith<HttpResponseMessage>(o =>
{
string file1 = provider.BodyPartFileNames.First().Value;
// this is the file name on the server where the file was saved
return new HttpResponseMessage()
{
Content = new StringContent("File uploaded.")
};
}
);
return task;
}
See the code below, adapted from this article, which demonstrates the simplest example code I could find. It includes both file and memory (faster) uploads.
public HttpResponseMessage Post()
{
var httpRequest = HttpContext.Current.Request;
if (httpRequest.Files.Count < 1)
{
return Request.CreateResponse(HttpStatusCode.BadRequest);
}
foreach(string file in httpRequest.Files)
{
var postedFile = httpRequest.Files[file];
var filePath = HttpContext.Current.Server.MapPath("~/" + postedFile.FileName);
postedFile.SaveAs(filePath);
// NOTE: To store in memory use postedFile.InputStream
}
return Request.CreateResponse(HttpStatusCode.Created);
}
The ASP.NET Core way is now here:
[HttpPost("UploadFiles")]
public async Task<IActionResult> Post(List<IFormFile> files)
{
long size = files.Sum(f => f.Length);
// full path to file in temp location
var filePath = Path.GetTempFileName();
foreach (var formFile in files)
{
if (formFile.Length > 0)
{
using (var stream = new FileStream(filePath, FileMode.Create))
{
await formFile.CopyToAsync(stream);
}
}
}
// process uploaded files
// Don't rely on or trust the FileName property without validation.
return Ok(new { count = files.Count, size, filePath});
}
Here is a quick and dirty solution which takes uploaded file contents from the HTTP body and writes it to a file. I included a "bare bones" HTML/JS snippet for the file upload.
Web API Method:
[Route("api/myfileupload")]
[HttpPost]
public string MyFileUpload()
{
var request = HttpContext.Current.Request;
var filePath = "C:\\temp\\" + request.Headers["filename"];
using (var fs = new System.IO.FileStream(filePath, System.IO.FileMode.Create))
{
request.InputStream.CopyTo(fs);
}
return "uploaded";
}
HTML File Upload:
<form>
<input type="file" id="myfile"/>
<input type="button" onclick="uploadFile();" value="Upload" />
</form>
<script type="text/javascript">
function uploadFile() {
var xhr = new XMLHttpRequest();
var file = document.getElementById('myfile').files[0];
xhr.open("POST", "api/myfileupload");
xhr.setRequestHeader("filename", file.name);
xhr.send(file);
}
</script>
I used Mike Wasson's answer before I updated all the NuGets in my webapi mvc4 project. Once I did, I had to re-write the file upload action:
public Task<HttpResponseMessage> Upload(int id)
{
HttpRequestMessage request = this.Request;
if (!request.Content.IsMimeMultipartContent())
{
throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.UnsupportedMediaType));
}
string root = System.Web.HttpContext.Current.Server.MapPath("~/App_Data/uploads");
var provider = new MultipartFormDataStreamProvider(root);
var task = request.Content.ReadAsMultipartAsync(provider).
ContinueWith<HttpResponseMessage>(o =>
{
FileInfo finfo = new FileInfo(provider.FileData.First().LocalFileName);
string guid = Guid.NewGuid().ToString();
File.Move(finfo.FullName, Path.Combine(root, guid + "_" + provider.FileData.First().Headers.ContentDisposition.FileName.Replace("\"", "")));
return new HttpResponseMessage()
{
Content = new StringContent("File uploaded.")
};
}
);
return task;
}
Apparently BodyPartFileNames is no longer available within the MultipartFormDataStreamProvider.
Toward this same directions, I'm posting a client and server snipets that send Excel Files using WebApi, c# 4:
public static void SetFile(String serviceUrl, byte[] fileArray, String fileName)
{
try
{
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
using (var content = new MultipartFormDataContent())
{
var fileContent = new ByteArrayContent(fileArray);//(System.IO.File.ReadAllBytes(fileName));
fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
{
FileName = fileName
};
content.Add(fileContent);
var result = client.PostAsync(serviceUrl, content).Result;
}
}
}
catch (Exception e)
{
//Log the exception
}
}
And the server webapi controller:
public Task<IEnumerable<string>> Post()
{
if (Request.Content.IsMimeMultipartContent())
{
string fullPath = HttpContext.Current.Server.MapPath("~/uploads");
MyMultipartFormDataStreamProvider streamProvider = new MyMultipartFormDataStreamProvider(fullPath);
var task = Request.Content.ReadAsMultipartAsync(streamProvider).ContinueWith(t =>
{
if (t.IsFaulted || t.IsCanceled)
throw new HttpResponseException(HttpStatusCode.InternalServerError);
var fileInfo = streamProvider.FileData.Select(i =>
{
var info = new FileInfo(i.LocalFileName);
return "File uploaded as " + info.FullName + " (" + info.Length + ")";
});
return fileInfo;
});
return task;
}
else
{
throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotAcceptable, "Invalid Request!"));
}
}
And the Custom MyMultipartFormDataStreamProvider, needed to customize the Filename:
PS: I took this code from another post http://www.codeguru.com/csharp/.net/uploading-files-asynchronously-using-asp.net-web-api.htm
public class MyMultipartFormDataStreamProvider : MultipartFormDataStreamProvider
{
public MyMultipartFormDataStreamProvider(string path)
: base(path)
{
}
public override string GetLocalFileName(System.Net.Http.Headers.HttpContentHeaders headers)
{
string fileName;
if (!string.IsNullOrWhiteSpace(headers.ContentDisposition.FileName))
{
fileName = headers.ContentDisposition.FileName;
}
else
{
fileName = Guid.NewGuid().ToString() + ".data";
}
return fileName.Replace("\"", string.Empty);
}
}
[HttpPost]
public JsonResult PostImage(HttpPostedFileBase file)
{
try
{
if (file != null && file.ContentLength > 0 && file.ContentLength<=10485760)
{
var fileName = Path.GetFileName(file.FileName);
var path = Path.Combine(Server.MapPath("~/") + "HisloImages" + "\\", fileName);
file.SaveAs(path);
#region MyRegion
////save imag in Db
//using (MemoryStream ms = new MemoryStream())
//{
// file.InputStream.CopyTo(ms);
// byte[] array = ms.GetBuffer();
//}
#endregion
return Json(JsonResponseFactory.SuccessResponse("Status:0 ,Message: OK"), JsonRequestBehavior.AllowGet);
}
else
{
return Json(JsonResponseFactory.ErrorResponse("Status:1 , Message: Upload Again and File Size Should be Less Than 10MB"), JsonRequestBehavior.AllowGet);
}
}
catch (Exception ex)
{
return Json(JsonResponseFactory.ErrorResponse(ex.Message), JsonRequestBehavior.AllowGet);
}
}
This question has lots of good answers even for .Net Core. I was using both Frameworks the provided code samples work fine. So I won't repeat it. In my case the important thing was how to use File upload actions with Swagger like this:
Here is my recap:
ASP .Net WebAPI 2
To upload file use: MultipartFormDataStreamProvider see answers here
How to use it with Swagger
.NET Core
To upload file use: IFormFile see answers here or MS documentation
How to use it with Swagger
Here are two ways to accept a file. One using in memory provider MultipartMemoryStreamProvider and one using MultipartFormDataStreamProvider which saves to a disk. Note, this is only for one file upload at a time. You can certainty extend this to save multiple-files. The second approach can support large files. I've tested files over 200MB and it works fine. Using in memory approach does not require you to save to disk, but will throw out of memory exception if you exceed a certain limit.
private async Task<Stream> ReadStream()
{
Stream stream = null;
var provider = new MultipartMemoryStreamProvider();
await Request.Content.ReadAsMultipartAsync(provider);
foreach (var file in provider.Contents)
{
var buffer = await file.ReadAsByteArrayAsync();
stream = new MemoryStream(buffer);
}
return stream;
}
private async Task<Stream> ReadLargeStream()
{
Stream stream = null;
string root = Path.GetTempPath();
var provider = new MultipartFormDataStreamProvider(root);
await Request.Content.ReadAsMultipartAsync(provider);
foreach (var file in provider.FileData)
{
var path = file.LocalFileName;
byte[] content = File.ReadAllBytes(path);
File.Delete(path);
stream = new MemoryStream(content);
}
return stream;
}
I had a similar problem for the preview Web API. Did not port that part to the new MVC 4 Web API yet, but maybe this helps:
REST file upload with HttpRequestMessage or Stream?
Please let me know, can sit down tomorrow and try to implement it again.
API Controller :
[HttpPost]
public HttpResponseMessage Post()
{
var httpRequest = System.Web.HttpContext.Current.Request;
if (System.Web.HttpContext.Current.Request.Files.Count < 1)
{
//TODO
}
else
{
try
{
foreach (string file in httpRequest.Files)
{
var postedFile = httpRequest.Files[file];
BinaryReader binReader = new BinaryReader(postedFile.InputStream);
byte[] byteArray = binReader.ReadBytes(postedFile.ContentLength);
}
}
catch (System.Exception e)
{
//TODO
}
return Request.CreateResponse(HttpStatusCode.Created);
}
Complementing Matt Frear's answer - This would be an ASP NET Core alternative for reading the file directly from Stream, without saving&reading it from disk:
public ActionResult OnPostUpload(List<IFormFile> files)
{
try
{
var file = files.FirstOrDefault();
var inputstream = file.OpenReadStream();
XSSFWorkbook workbook = new XSSFWorkbook(stream);
var FIRST_ROW_NUMBER = {{firstRowWithValue}};
ISheet sheet = workbook.GetSheetAt(0);
// Example: var firstCellRow = (int)sheet.GetRow(0).GetCell(0).NumericCellValue;
for (int rowIdx = 2; rowIdx <= sheet.LastRowNum; rowIdx++)
{
IRow currentRow = sheet.GetRow(rowIdx);
if (currentRow == null || currentRow.Cells == null || currentRow.Cells.Count() < FIRST_ROW_NUMBER) break;
var df = new DataFormatter();
for (int cellNumber = {{firstCellWithValue}}; cellNumber < {{lastCellWithValue}}; cellNumber++)
{
//business logic & saving data to DB
}
}
}
catch(Exception ex)
{
throw new FileFormatException($"Error on file processing - {ex.Message}");
}
}

Categories