Asp.Net Mvc: How to get uploaded file actual path - c#

I am using HTML input file to select the file. I have tried in JQUERY but I it returns fake path.
$("#inputfile").val()
I want to get selected file actual path e.g
D:\Documents\image.png
So I have tried to upload the file in ASP.NET MVC and check the path but It also gives file name.
[HttpPost]
public ActionResult GetFileName() {
var result = "";
if (Request.Files.Count > 0)
{
result = Request.Files[0].FileName;
}
return Json(result);
}
Is there any solution to get the path. I know this a browser security feature but I have to entertain the client requirement. Please suggest the solution if exist.
Thank you

Short answer - no way.
You cannot get the client's file path, only the filename.

Related

Why can't I access static files that I add programmatically from a POST request?

I'm attempting to make a basic .NET API for managing a collection of media (images and videos).
I have configured the webroot to be a folder called "site", and within that folder is a folder called "media" where these files are stored. I can access a test media file that is saved in /site/media/Smush.jpg by loading https://localhost:5001/site/media/smush.jpg - this serves the image as expected.
I have created a method that receives a POST request containing form data from my frontend, and this method saves the file to the webroot using a filestream, code below:
[HttpPost]
[Route("/media/add")]
public async Task<HttpResponseMessage> MediaAdd()
{
try
{
//get the form
var form = HttpContext.Request.Form;
//if there's a route, add it into the filepath, otherwise leave it out and have the filepath go straight to media (this prevents an exception if route is blank)
string filePath = form["route"] == "" ? Path.Combine(_hostingEnvironment.WebRootPath, "media") : Path.Combine(_hostingEnvironment.WebRootPath, "media", form["route"]);
//get the first (should be only) image - DO WE WANT TO BE ABLE TO ADD MULTIPLE IMAGES? PROBABLY TBH
IFormFile image = form.Files.First();
if (image.Length > 0)
{
//check the directory exists - create it if not
if (!Directory.Exists(filePath)) {
Directory.CreateDirectory(filePath);
}
using (Stream fileStream = new FileStream(Path.Combine(filePath, form["filename"]), FileMode.Create))
{
await image.CopyToAsync(fileStream);
return new HttpResponseMessage(HttpStatusCode.OK);
}
}
else {
return new HttpResponseMessage(HttpStatusCode.BadRequest);
}
}
catch (Exception e)
{
return new HttpResponseMessage(HttpStatusCode.BadRequest);
}
}
My frontend submits a route, filename and the media file, and this is used to save the image. This all works fine; I can submit an image with the path "test" and the name "test.jpg", and the API correctly stores the file at /site/media/test/test.jpg. I can view the file in the solution and see a preview of the image, as with Smush.jpg.
However, attempting to load https://localhost:5001/site/media/test/test.jpg results in a 404. Why is this the case? Can I not add files into the webroot through code and have them be accessible as static files as if I added them to the solution in my IDE? Are there any alternative ways of handling this?
I am using .NET 5.0, and have
app.UseStaticFiles(); in Configure() in Startup.cs.
Sorry if this is a duplicate, but I couldn't find anything else like this.
EDIT:
On checking things again, it seems like rather than my files being at https://localhost:5001/site/media, they are simply in https://localhost:5001/media. I am not sure how I was able to access Smush.jpg at https://localhost:5001/site/media/Smush.jpg before.
It seems as though the webroot is not included as part of a URL to access files within it.
As it is now, I have got what I was looking for it to do.
Well first a security concern as also #Heinzi pointed out...
string filePath = form["route"] == "" ? Path.Combine(_hostingEnvironment.WebRootPath, "media") : Path.Combine(_hostingEnvironment.WebRootPath, "media", form["route"]);
What if the user sends form.route == "../../" and instead of image he updates the appsettings.json file ?
Check this out and have that in mind if you're planing to release this code to a production environment and make sure you only accept image files.
On the other hand if you are serving static files from a folder different to wwwroot please use this configuration
Why the 404
It makes sense. You are under the controller/action paths. Going under the site url the engine does the following:
When you request https://localhost:5001/site/media/test/test.jpg the code tries to find the media controller and the test action. It is not looking for static files on the filesystem. Since there is no such controller/action pairs, it will not find anything and thus return 404 not found.
If you saved the files in https://localhost:5001/static/media/test.jpg outside of the mapped routes, you would be able to access it.
Look inside your code for:
MapHttpRoute
Which is used to configure how to identify controller actions which are not decorated with the [Route] attribute.
Security concern
When you want to upload a file, you should consider a better solution and not one that accesses directly your filesystem.
Possible options:
Blob storage on the cloud
Database blobs
Don't forget to sanitize the input with an antivirs or some similar solution.

Get data in file without indicating a particular filepath

I am tasked to create a web service API where for an example, when an URL http://localhost:12345/api/filereader/data.txt is entered in the web browser, the data which is in data.txt file has to be displayed in the web page. I am able to do it if I know the filepath of data.txt.
However another requirement is that I am not supposed to indicate the filepath (in my code) as the scenario is, user is supposed to be able to use the URL API and input the .txt file name as a parameter (from whichever computer/server they are using) to get the data of what is in the .txt file that they have indicated. Therefore there should not be any physical path in my code. Is it possible to achieve that?
Here is the code that I have tried (with filepath):
ReaderController.cs
[ResponseType(typeof(string))]
public IHttpActionResult Get(String FileName)
{
try
{
string fileName = FileName;
string path = "C:\\Users\\attsuap1\\Desktop\\" + fileName;
string result = File.ReadAllText(path);
var resultDTO = JsonConvert.DeserializeObject(result);
return Ok(resultDTO);
}
catch
{
var result = "File does not exist";
return Ok(new { ErrorMessage = result });
}
}
How do I edit this code to get what I want?
You are asking to load a file from a user device from your server. That is just not possible for security purposes (imagine what would happen if you could).
The only way to get access to a file from the user, is by letting the user send it using some sort of upload form or control. The posted data can be used by your server then.

Want to upload file in the live server other than App_Data folder in ASP.Net MVC

I need to upload an image in ~/Images/Item folder in live server. I can upload in ~/App_Data/Images folder without any exception. But when I'm trying to upload in ~/Images/Item, it gives me exception with message "A generic error occurred in GDI+".
I have searched already but did not find any solution that worked for me. Any kind of suggestion will be appreciated.
You can do something like this. Pleasemake sure that that application have write permission to this folder.
[HttpPost]
public ActionResult Index(HttpPostedFileBase file) {
// Verify that the user selected a file
if (file != null && file.ContentLength > 0) {
// extract only the filename
var fileName = Path.GetFileName(file.FileName);
// store the file inside ~/App_Data/uploads folder
var path = Path.Combine(Server.MapPath("~/Images/Item"), fileName);
file.SaveAs(path);
}
return RedirectToAction("Index");
}

how to return image url instead of file path

I am facing an issue when showing uploaded image in browser.
I get error
Not allowed to load local resource:
file:///C:/Office%20Data/dummy/AngularJSAuthentication-master/MyCars/MyCar.API/App_Data/Images/p7.jpeg%20alt=
I wrote the following line of code to store image on server under App_data.
File.Path = Url.Content(string.Format("{0}/{1}", System.Web.HttpContext.Current.Server.MapPath("~/App_Data/Images"), fileName));
File path saved in DB as following
file:///C:/Sample%20Data/dummy/AngularJSAuthentication-master/MyCars/MyCar.API/App_Data/Images/p7.jpeg
HTML
<img ng-src="{{motor.FileUploads[0].Path}} alt="Description" />
After googling i got the reason for this error.
Basically i need to return back Image URL instead of file path.
Problem:
I am not sure how i can return image path back to angular client.
Can someone guide me on it.
You don't need to specify the complete physical path, when reference from the browser
File.Path = Url.Content(string.Format("~/App_Data/Images/{0}", fileName));
this should return the relative URL
Update : well this won't work since you can directly access contents of the app_data folder. you can approach this either of these ways
move the images out of the app_data folder to like ~/images folder
and it should work or
keep the file in the app_data folder but stream the file using
content/file result action on one of your controllers
bare minimum sample implementation of the second option would look like
public class UploadsController : Controller
{
[HttpGet]
public ActionResult Image( string fileName )
{
//!validate file name!
return File( Server.MapPath( $"~/App_Data/{fileName}" ), "image/jpeg" );
}
}
then in the HTML it can be referenced as <img src="api/uploads/image?filename=temp.jpg" ...
Just drop everything except the file name if all your images are in the root of Images:
//using System.IO;
File.Path = Url.Content(string.Format("{0}/{1}", System.Web.HttpContext.Current.Server.MapPath("~/App_Data/Images"), Path.GetFileName(fileName)));
Update
should have been like Sam's answer:
File.Path = Url.Content(string.Format("~/App_Data/Images/{0}",Path.GetFileName(fileName)));

How to get the Filename(s) Uploaded using the Ajax Uploader

I am Uploading the Multiple files to the DB using the Ajax File Uploder, I need to get the names of the files without the Extension like we do in normal file Control.Does any one knows that is there any way to get the filenames Uploaded using the Ajax Uploader.
I had searched in the Google and seen many sites but I haven't found any helpful links.
I anybody knows some helpful links or Code kindly Suggest Me.
You can use Request.Files to get the files submitted to your page.
e.g.
if (Request.Files.Count > 0)
{
HttpPostedFile ObjFile = Request.Files[0];
string filename = strTick + System.IO.Path.GetFileNameWithoutExtension(ObjFile.FileName);
string originalName = ObjFile.FileName;
}

Categories

Resources