file storage .net core - c#

i'm using a folder inside my project to upload files .
[HttpPost, DisableRequestSizeLimit]
public IActionResult Upload()
{
try
{
var file = Request.Form.Files[0];
var folderName = Path.Combine("Resources", "Images");
var pathToSave = Path.Combine(Directory.GetCurrentDirectory(), folderName);
if (file.Length > 0)
{
var fileName = ContentDispositionHeaderValue.Parse(file.ContentDisposition).FileName.Trim('"');
var fullPath = Path.Combine(pathToSave, fileName);
var dbPath = Path.Combine(folderName, fileName);
using (var stream = new FileStream(fullPath, FileMode.Create))
{
file.CopyTo(stream);
}
return Ok(new { dbPath });
}
else
{
return BadRequest();
}
}
catch (Exception ex)
{
return StatusCode(500, $"Internal server error: {ex}");
}
}
i was wondering if there's a risk to lose this files when we have new update for the customer .
if there's a better solution for upload file and getting file link afterwards with .net core please let me know :)

i was wondering if there's a risk to lose this files when we have new update for the customer
Deploying an application means, you'll copy the new executables (dlls) and other files stored in git to the place where the old version is running. Risk is, that you'll do it wrong and delete the data directory.
That said: You should not save user data together with your executables or other files that are part of your app (e.g. images used in HTML, ...). It's much easier to handle (backups, deployments, ...) if data is clearly separated.
if there's a better solution
The solution: Save it in a folder that can be configured by admins. This can be done using so called Options: https://learn.microsoft.com/en-us/aspnet/core/fundamentals/configuration/options?view=aspnetcore-3.1
You'll end up with a class that stores your path
public class StorageOptions {
public string BasePath {get;set;}
}

so at the end i decided to use 'aws S3 bucket' using this code
PutObjectResponse response = null;
using (var stream = new MemoryStream(fileBytes))
{
var request = new PutObjectRequest
{
BucketName = bucket,
Key = "folder/" + fileName,
InputStream = stream,
ContentType = file.ContentType,
CannedACL = S3CannedACL.PublicRead,
};
response = await client.PutObjectAsync(request);
};
and as you mentioned in comments i can get the link afterwards of the file

Related

Receiving binary Data from a rest endpoint

I am new to API/Rest endpoints, so please forgive my inexperience on this topic.
I am using .net core 3.1. And i have been tasked to write an endpoint, that excepts two parameters a string and a file..
The file will be of binary data (a .bci file format, which i assume is a custom one, but all it is basically is a .txt file, that has been changed to .bci for a machine)
I need to get the file and then read the file using a stringReader and saved to a file locally. Again i am new to endpoints and reading binary data, can anyone help? i have been looking all over the internet today but with no prevail.
I know the below code is incorrect, but really struggling on this one. Any help would much be appreciated.
//GET: api/ProcessResultsFiles]
[HttpGet]
public async Task<IActionResult> ProcessResults(IFormFile file, string bench)
{
await ReadData(file);
return Ok();
}
private static Task<byte[]> ReadData(IFormFile benchNameFile)
{
using (StringReader sr = new StringReader(benchNameFile))
{
string input = null;
while ((input = sr.ReadLine()) != null)
{
Console.WriteLine(input);
}
}
}
From your description, I assume you want to upload the file to the Physical storage/folder, after that might be you want to download the file to local, if that is the case, you could refer the following sample:
[HttpPost("upload")]
public IActionResult Upload(List<IFormFile> formFiles, string subDirectory)
{
try
{
subDirectory = subDirectory ?? string.Empty;
var target = Path.Combine(_environment.WebRootPath, subDirectory);
if(!Directory.Exists(target))
Directory.CreateDirectory(target);
formFiles.ForEach(async file =>
{
if (file.Length <= 0) return;
var filePath = Path.Combine(target, file.FileName);
using (var stream = new FileStream(filePath, FileMode.Create))
{
await file.CopyToAsync(stream);
}
});
return Ok("Upload success!");
}
catch (Exception ex)
{
return BadRequest(ex.Message);
}
}
[HttpPost("download")]
public IActionResult DownLoad( string subDirectory, string filename)
{
//Build the File Path.
string path = Path.Combine(_environment.WebRootPath, subDirectory +"/"+ filename);
if (System.IO.File.Exists(path))
{
//Read the File data into Byte Array.
byte[] bytes = System.IO.File.ReadAllBytes(path);
//download the file.
return File(bytes, "application/octet-stream", filename);
}
else
{
return Ok("file not exist");
}
}
The result as below:
More detail information about upload file in asp.net core, you can refer the following articles:
Upload files in ASP.NET Core
Upload And Download Multiple Files Using Web API
From the above articles, when upload file, if you want to save the byte array, you can refer the following code:
public async Task<IActionResult> OnPostUploadAsync()
{
using (var memoryStream = new MemoryStream())
{
await FileUpload.FormFile.CopyToAsync(memoryStream);
// Upload the file if less than 2 MB
if (memoryStream.Length < 2097152)
{
var file = new AppFile()
{
Content = memoryStream.ToArray()
};
_dbContext.File.Add(file);
await _dbContext.SaveChangesAsync();
}
else
{
ModelState.AddModelError("File", "The file is too large.");
}
}
return Page();
}

What permissions are required to upload to WWWRoot folder in ASP.NET Core API

I have created asp.net core 2.2 web API + MVC project and I am trying to upload a file to WWWRoot folder. I get access denied error when trying to upload file.
I would like to know appropriate accounts and required permissions to enable write access
I have applied UseStaticFiles in Startup file.
Here's code to upload file:
public async Task<IActionResult> Create(FileuploadRequest fileuploadRequest)
{
if (!ModelState.IsValid)
{
return BadRequest();
}
else
{
if (fileuploadRequest.Logo.Length > 0)
{
string webRootPath = _hostingEnvironment.WebRootPath;
var folderPath = Path.Combine(webRootPath,"Resources\\Images");
using (var fileStream = new FileStream(folderPath, FileMode.Create))
{
await fileuploadRequest.Logo.CopyToAsync(fileStream);
}
As Joe suggested ,make sure that the folder exists and try to append the fileName to your folder path like below:
if (fileuploadRequest.Logo.Length > 0)
{
string webRootPath = _hostingEnvironment.WebRootPath;
var fileName = Path.GetFileName(fileuploadRequest.Logo.FileName);
var folderPath = Path.Combine(webRootPath,"Resources\\Images",fileName);
using (var fileStream = new FileStream(folderPath, FileMode.Create))
{
await fileuploadRequest.Logo.CopyToAsync(fileStream);
}
Using below of code work for me
public async Task<string> UploadAssets(IFormFile file, string fileName)
{
string storePath = "";
try
{
storePath = Path.Combine(_assetSettings.Value.StorePath, $"{fileName}.{file.ContentType.Split("/")[1]}");
using (var stream = new FileStream(storePath, FileMode.Create))
{
await file.CopyToAsync(stream);
}
}
}
Also try to run your Visual studio in Administrator right to allow full access to file, folder in your computer

Upload file uploaded via HTTP to ASP.NET further to SFTP server in C# and SSH.NET

I'm setting up a file transfer through Renci SSH.NET library using SFTP and C#.
And I'm stuck on this problem.
Whenever I upload a file in my ASP .NET Core program it sends the file, but it sends it as an empty file with the same name.
public async Task<IActionResult> UploadFiles(List<IFormFile> files)
{
string host = "----";
string username = "----";
string password = "----";
string Name = "";
var Stream = new MemoryStream();
List<MemoryStream> stream = new List<MemoryStream>();
var connectionInfo = new Renci.SshNet.ConnectionInfo(host, username, new PasswordAuthenticationMethod(username, password));
var sftp = new SftpClient(connectionInfo);
sftp.Connect();
sftp.ChangeDirectory("DIRECTORY");
try
{
//Read the FileName and convert it to Byte array.
foreach (var formFile in files)
{
var memoryStream = new MemoryStream();
await formFile.CopyToAsync(memoryStream);
Name = formFile.FileName;
using (var uplfileStream = memoryStream)
{
sftp.UploadFile(uplfileStream, Name, null);
}
}
}
catch (WebException ex)
{
throw new Exception((ex.Response as FtpWebResponse).StatusDescription);
}
sftp.Disconnect();
return View("Inbox");
}
I expect an output where a file is uploaded to the server, but the actual output is a file being uploaded to the server with the same name as the file I tried to upload, but the size is 0kb aka its empty.
Your immediate problem is answered here:
Upload from ByteArray/MemoryStream using SSH.NET - File gets created with size 0KB
Though you do not need the intermediate MemoryStream (and it's inefficient anyway).
Use IFormFile.OpenReadStream:
using (var uplfileStream = formFile.OpenReadStream())
{
sftp.UploadFile(uplfileStream, Name);
}

Uploading file in ASP.NET to server

I'm working on a website where users could apply to a certain job online.
A user must submit information in addition to a CV.
I'm new to this kind of work I would appreciate any kind of help.
Here is my attempt for the post method, but it generates the following exception:
Unexpected end of stream. Is there an end boundary?
public async Task<IHttpActionResult> PostCV()
{
IList<string> AllowedFileExtensions = new List<string> { ".txt", ".pdf" };
var parser = new MultipartFormDataParser(await Request.Content.ReadAsStreamAsync());
IList<FilePart> files = parser.Files;
IList<ParameterPart> formData = parser.Parameters;
FilePart uploadedContent = files.First();
var originalContentFileName =
uploadedContent.FileName.Trim('\"');
var originalExtension = Path.GetExtension(originalContentFileName);
if (!AllowedFileExtensions.Contains(originalExtension))
return BadRequest("Bad extension");
string modifiedContentFileName =
string.Format("{0}{1}", Guid.NewGuid().ToString(),
originalExtension);
Stream input = uploadedContent.Data;
string Url = string.Empty;
string fileName = string.Empty;
string directoryName = string.Empty;
directoryName = Path.Combine(HttpRuntime.AppDomainAppPath, "Uploads");
fileName = Path.Combine(directoryName, modifiedContentFileName);
if (File.Exists(fileName))
File.Delete(fileName);
using (Stream file = File.OpenWrite(fileName))
{
try
{
input.CopyTo(file);
file.Close();
var cv = new CV{ Path = fileName };
db.CVs.Add(cv);
db.SaveChanges();
return Json(cv);
}
catch (Exception ex)
{
return BadRequest(ex.Message);
}
}
}
Thanks in advance
Apparently I should have chosen form-data in the body section, set the key with anything (e.g filename) and in the value choose file.
Also you need to create a folder in your path, in my case called Uploads in the directory specified.
Lots of thanks for those who helped.

Why do I get a permission error in the OpenUrl function on an iOS device when trying to read in the file that has been sent to my app?

I have my Info.plist file setup to handle the file type I want. When I download the file in Safari, and pick my App from the Open In, the file does get sent to my app and the OpenUrl function is called. In the Simulator, I am able to open the file using FileStream and process it without any problem. On the real device, I get an error that says something like:
Accesss to the path "/private/var/mobile/Containers/Data/Application/{KEY}/Documents/Inbox/file.ext is denied.
Here is my OpenUrl function:
public override bool OpenUrl(UIApplication application, NSUrl url, string sourceApplication, NSObject annotation)
{
try
{
System.Console.WriteLine("OpenURL");
var fileName = url.AbsoluteUrl.LastPathComponent;
var newPath = Path.Combine(bookStorage, fileName);
var input = new System.IO.FileStream(url.Path, FileMode.Open);
var output = new System.IO.FileStream(newPath, FileMode.Create);
input.CopyTo(output);
output.Close();
input.Close();
var epub = new EpubParser(bookStorage, fileName);
var publication = new Publication(epub.getTitle(), fileName);
var id = epub.getId();
if (id != null)
{
publication.Id = id;
}
publication.Picture = epub.getImage();
var publications = new Publications();
publications.AddPublication(publication);
return true;
}
catch (Exception e)
{
var navController = (UINavigationController)this.Window.RootViewController;
var controller = navController.ViewControllers[0];
AlertView.Show(e.Message, controller);
return false;
}
}
Basically all I wanted was to copy the file to another location to keep it stored. So I used File.Copy instead and it worked! Apparently FileStream even with just the Open permissions set, still requires some type of write access to the folder.
var fileName = url.AbsoluteUrl.LastPathComponent;
var newPath = Path.Combine(bookStorage, fileName);
File.Copy(url.Path, newPath);

Categories

Resources