File upload to wwwroot folder in ASP.NET Core - c#

Why is my following codes sometimes work, but sometimes it does't work?
private bool UploadFile(IFormFile ufile, string fname)
{
if (ufile.Length > 0)
{
string fullpath = Path.Combine(_env.WebRootPath, fname);
using (var fileStream = new FileStream(fullpath, FileMode.Create))
{
ufile.CopyToAsync(fileStream);
}
return true;
}
return false;
}
The code did managed to save the picture to a folder which I created under wwwroot, but the picture is not appearing, and even in Visual Studio too.
Is there a way to solve it?
Thanks.
Even when I open up the file explorer of the folder that is storing the pictures, the picture is like is there but not showing any image.

Try as follows. File will be uploaded to images folder under wwwroot folder.
private async Task<bool> UploadFile(IFormFile ufile)
{
if (ufile != null && ufile.Length > 0)
{
var fileName = Path.GetFileName(ufile.FileName);
var filePath = Path.Combine(Directory.GetCurrentDirectory(), #"wwwroot\images", fileName);
using (var fileStream = new FileStream(filePath, FileMode.Create))
{
await ufile.CopyToAsync(fileStream);
}
return true;
}
return false;
}

Had same problem with dot net core, here's what I did:
-Make virtual directory
-Map it to that folder path (inside wwwroot)
-Make your fullpath equals to this VD ; absolute path (can keep it in config file)
-Give write permissions for this folder to iisuser

allow accessing to static files, just add this line in you startup.cs file under Configure method:
app.UseStaticFiles();

Related

Dotnet controller unable to save gif files

I'm making a converter that receives some image/video and does the process to turn it into a webp file.
With jpg, png and webm files i don't have any problem at all, but for some reason when I attempt to use a gif file I got this error: "Access to the path 'C:\Users\Desktop\computing\api\wwwroot\spin.gif' is denied."
This error occurs when i`m trying to save the file received by a IFormFile.
My controller is like this:
[HttpPost]
[DisableRequestSizeLimit]
public async Task<IActionResult> ConverterToWebp()
{
var webp = new WEBPConverter(new VideoSettings(_videoSettings));
var workingdir = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot");
var (file, _) = GetFile();
if (file == null)
return BadRequest("Arquivo inválido");
var (filepath, _) = await SaveToDir(file, workingdir);
var res = await webp.ConverterWebp(filepath);
if (!res.Success)
return BadRequest(res);
return File(res.bytes, "image/webp");
}
The method GetFile() look like this:
private (IFormFile? file, string? mimetype) GetFile()
{
var files = HttpContext.Request.Form.Files;
var file = files.FirstOrDefault();
if (file == null || file.Length == 0)
return (null, null);
var contentTypeProvider = new FileExtensionContentTypeProvider();
var isBlob = file.FileName.ToLower() == "blob";
var mimetypeParseOk = contentTypeProvider.TryGetContentType(file.FileName, out var mimeType);
if (isBlob)
return (file, "blob");
if (mimetypeParseOk)
return (file, mimeType);
return (null, null);
}
And the method who trigger the error, SaveToDir(), look like this:
private async Task<(string filepath, string filename)> SaveToDir(IFormFile file, string path)
{
var filename = new string(file.FileName
.Replace(' ', '_')
.Normalize(NormalizationForm.FormD)
.Where(ch => char.GetUnicodeCategory(ch) != UnicodeCategory.NonSpacingMark)
.ToArray());
var filepath = Path.Combine(path, filename);
using var stream = new FileStream(filepath, FileMode.Create);
await file.CopyToAsync(stream);
return (filepath, filename);
}
The entire project is using .net core 6.0
If I take one file with .gif extension and change it to .webm I got no error, even though the conversion don`t works great.
I don't know the reason why only if i use gif this method to save in directory don't work and generate that generic error because the path exist and has permissions, and that's why it doesn't trigger error in other files types.
By default IIS does not have permission for the wwwroot folder. You need to grant permissions to the IIS_IUSRS for the folder. I would not recommend this approach as it may be a potential security risk. The approach you could take is:
string path = Path.Combine(Path.GetTempPath(), Path.GetTempFileName());
With this you would save the file to the temp folder and temp file name in the users temp folder, in this case the assigned application user or by default IIS_IUSRS. Don't forget to delete the file after you're done with it.
In the case you want to go with the path of granting the access you do the following:
Go to where your inetpub folder is located
Right click on wwwroot and click on Properties
Switch to the security tab and click Edit...
Look for the IIS_IUSRS user, should be PCNAME\IIS_IUSRS
Select Allow for all permissions.
In the end I managed to solve the problem by saving a file without extesion and using theirs bytes arrays to convert.
But in fact the original question is not solved, any file that I try to use and that has the gif's extension get error. I tried to test changing a webm file that's working with name "test.webm" to "test.gif" and get the same error of permission.
This is how my method got no error:
private async Task<(string filepath, string filename)> SaveToDir(IFormFile file, string path)
{
var timespanEpoch = (int)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds;
var filename = $"web_temp_file-{timespanEpoch}";
var filepath = Path.Combine(path, filename);
using var stream = new FileStream(filepath, FileMode.Create);
await file.CopyToAsync(stream);
return (filepath, filename);
}

Upload Csv to solution explorer

I'm trying to build an application in which a user can upload a csv file and convert it into XML. Currently my controller can create .txt file in a temp folder. However when I open the txt file it comes out all corrupted as below:
I have two questions
1. How can I make it so that the file displays properly i.e. as items separated by commas?
2. How can I change my code to make the file upload into my solution explorer
Here is the relevant controller code:
[HttpPost("UploadFiles")]
public async Task<IActionResult> FileUpload(List<IFormFile> files)
{
long size = files.Sum(f => f.Length);
var filePaths = new List<string>();
foreach (var formFile in files)
{
if(formFile.Length > 0)
{
var filePath = Path.GetTempPath()+ Guid.NewGuid().ToString()+".txt";
filePaths.Add(filePath);
using (var stream = new FileStream(filePath, FileMode.Create, FileAccess.ReadWrite))
{
await formFile.CopyToAsync(stream);
}
}
}
return Ok(new { count = files.Count, size, filePaths });
}
Any suggestions would be much appreciated
Thanks in advance
When the file is corrupt I think the conversion doesn't work. Try for now uploading it without any conversion.
For the second question you can do the following
var filePath = Path.Combine(AppContext.BaseDirectory, $"{Guid.NewGuid().ToString()}.csv"); // or whatever extension you are actually having without modifying the original extension
This will store the file either in the "bin" directory path or in the directory where the source-code is located.

File upload to create directory ASP.Net core mac os doesn't create sub folder

I'm using asp.net core to create a project to upload the file in specific location in the server.
Here is the code:
TempFileName = Regex.Replace(vehicle.FileUpload.FileName, "[^a-zA-Z0-9_]+", "_", RegexOptions.Compiled);
var directiveToUpload = Path.Combine(_hostingEnvironment.WebRootPath, "images\\UploadFile");
if (!System.IO.Directory.Exists(directiveToUpload))
{
System.IO.Directory.CreateDirectory(directiveToUpload);
}
await SaveFileToServer(TempFileName);
Save the file:
async Task SaveFileToServer(string FileName)
{
if (vehicle.FileUpload.Length > 0)
{
using (var stream = new FileStream(Path.Combine(directiveToUpload, FileName), FileMode.Create))
{
await vehicle.FileUpload.CopyToAsync(stream);
}
}
}
Since the file Get uploaded But it doesn't create sub folder on mac. images\UploadFile this is not working.
Can't reproduce this issue, but since directory separator is not \ on Mac, I guess it does not interpret it correctly. You could replace your code with the usage of Path.DirectorySeparatorChar constant to avoid this.
var directiveToUpload = Path.Combine(_hostingEnvironment.WebRootPath, "images\\UploadFile");
Would become
var directiveToUpload = Path.Combine(_hostingEnvironment.WebRootPath, $"images{Path.DirectorySeparatorChar}UploadFile");

How to give an absolute path in sever map method?

I have a folder which contains several PDF files and inserting and viewing all these pdf's are dont by 2 methods. I have to move this folder to place this folder outside of the project file. Therefore I have to use the absolute path. I have tried some coeds in the internet but none of them worked for me.
Following code is in a button clcik event
string directoryPath = #"D:\competion\pdfFolder\";
string svrPath = Server.MapPath(directoryPath);
DataSet ds = new DataSet();
string extension = Path.GetExtension(FileUpload1.FileName);
if ((FileUpload1.HasFile))
{
if (extension == ".pdf")
{
if (grdPolicyDetails.Rows.Count > 0)
{
//Few methods are invoked in the body
}
}
}
There are else parts in the if else statements but i haven't added those codes.
The Server.MapPath method works only with relative paths that are part of the web application structure. If you need to serve PDF files that are located outside, you might need to have some endpoint that will read the file contents on the server and stream it to the client.
For example:
string pdfPath = #"D:\competion\pdfFolder\myfile.pdf";
this.Response.ContentType = "application/pdf";
this.Response.TransmitFile(pdfPath);
this.Response.End();
I created a test project without the folder 'testVirPath'.
In my iis, I added a Virtual Directory that pointed to a folder (testVirPath) on a different drive (other than my project or published drive).
I added the necessary permissions and the same user as my published site on the localhost.
I then added some pdf files to the testVirPath folder and published the project to iis.
Try it.
This will list the pdf files stored on the testVirPath folder.
[Home Controller]
public ActionResult Files()
{
ViewBag.TheFiles = GetFiles(Server.MapPath("/testVirPath/"));
return View();
}
private FileInfo[] GetFiles(string path)
{
DirectoryInfo di = new DirectoryInfo(path);
FileInfo[] files = di.GetFiles();
return files;
}
[Files View]
<div>
#foreach (FileInfo f in #ViewBag.TheFiles)
{
<p>#f.FullName</p>
}
</div>
string directoryPath = Server.MapPath("~/competion/pdfFolder/");
try this !!
Kindly Use these code for pdf upload.
if (fuDoc.HasFile)
{
string ext = "";
string fnm = Path.GetFileName(fuDoc.PostedFile.FileName).ToLower();
ext = Path.GetExtension(fuDoc.PostedFile.FileName).ToLower();
if ((ext != ".doc") & (ext != ".pdf") & (ext != ".docx"))
{
Page.ClientScript.RegisterStartupScript(GetType(), "msgbox", "alert('Please select .doc or .pdf or .docx files only');", true);
fuDoc.Focus();
return;
}
fuDoc.PostedFile.SaveAs(Server.MapPath("~/Upload/Documents/") + fuDoc.FileName);
strDoc = "Upload/Documents/" + fuDoc.FileName;
}

How to recursively copy file an folder in .Net?

I have the following script, which take a source folder and copy using FileStream files to another folder.
I need to change it in a way to recursively get any sub-folders and copy their files too.
How to modifythe method?
- source folder
- file
- file
- folder
- file
- file
- folder
- file
- folder
- file
- file
- folder
- file
public static void SynchFolders()
{
DirectoryInfo StartDirectory = new DirectoryInfo(SourceUNC);
DirectoryInfo EndDirectory = new DirectoryInfo(TargetUNC);
foreach (FileInfo file in StartDirectory.EnumerateFiles())
{
using (FileStream SourceStream = file.OpenRead())
{
string dirPath = StartDirectory.FullName;
string outputPath = dirPath.Replace(StartDirectory.FullName, EndDirectory.FullName);
using (FileStream DestinationStream = File.Create(outputPath + "\\" + file.Name))
{
SourceStream.CopyToAsync(DestinationStream);
}
}
}
}
Basically what you need to do is to expand your function slightly such that after copying all files found in a particular directory, it will then search for subfolders within the current folder and recurse into that folder so that the same procedure is carried out on each subfolder.
An example function, based on your original code :
public static void SynchFolders(string SourceUNC, string TargetUNC)
{
DirectoryInfo StartDirectory = new DirectoryInfo(SourceUNC);
DirectoryInfo EndDirectory = new DirectoryInfo(TargetUNC);
// Copy Files
foreach (FileInfo file in StartDirectory.EnumerateFiles())
{
using (FileStream SourceStream = file.OpenRead())
{
string dirPath = StartDirectory.FullName;
string outputPath = dirPath.Replace(StartDirectory.FullName, EndDirectory.FullName);
using (FileStream DestinationStream = File.Create(outputPath + "\\" + file.Name))
{
SourceStream.CopyToAsync(DestinationStream);
}
}
}
// Copy subfolders
var folders = StartDirectory.EnumerateDirectories();
foreach (var folder in folders)
{
// Create subfolder target path by concatenating folder name to original target UNC
string target = Path.Combine(TargetUNC, folder.Name);
Directory.CreateDirectory(target);
// Recurse into the subfolder
SynchFolders(folder.FullName, target);
}
}
Hope this helps
How to: Copy Directories is an article from MSDN showing how to do exactly what you need.
Read this MSDN Tutorial (exacly what you need): http://msdn.microsoft.com/en-us/library/bb762914(v=vs.110).aspx
Note: if you'd like to use SourceStream.CopyToAsync instead of file.CopyTo, just replace it with your original snippet

Categories

Resources