How can I add images into my .resx file? - c#

By other than using AddResource button of Visual Studio, of course.
I submit a form, and an image file with it. In my controller action, I get the HttpPostedFileBase object, and its file name by using Path.GetFileName(). If I just use SaveAs() function to save the image file in my application, I cannot access it later for testing, because it gives me the "Not allowed to load local resource" error.
So I want to add the image to a .resx file and retrieve it later using ResourceManager or something. My question is, how can I add the image I have in the controller action into my .resx file?
I should also ask if this is the good approach for the purpose of adding and retrieving image files in my application.
EDITED:
Ok, using .resx to store images is not a good idea. My original problem was that I could save the image file, but when I tried to show it in my view, it gives "Not allowed to load local resource" error.
Here's the controller code:
public ActionResult UrunEkle(Urun urun, HttpPostedFileBase image)
{
Directory.CreateDirectory(Server.MapPath("~/App_Data/Images"));
var path = Path.Combine(Server.MapPath("~/App_Data/Images"), fileName);
image.SaveAs(path);
urun.ArtUrl = path;
// other stuff....
}
And in my view, I try to retrieve the image like this:
<img alt="#urun.name" src="#Url.Content(urun.ArtUrl)" />
But using Google Chrome, I get this "Not allowed to load local resource". How can I avoid this?

Forget trying to add the image to a RESX file; it's not designed to be modified at runtime.
Please post some code. The most likely thing is that the URL that you're serving up to use the image later is incorrect. Probably because you're returning the path of the file on the server, not a URL to the image within the context of the web site.
The error message from Chrome is telling you that it's trying to load a resource from the local file system on the client.
Url.Content converts a relative virtual path into an absolute virtual path and needs a URL starting with ~. You're currently passing in the absolute physical path to the image file and Url.Content is returning it, unchanged. You need the relative virtual path (~/App_Data/Images/Untitled.png) in urun.ArtUrl. This is the value that you passed in to Server.MapPath.

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.

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

save and retrieve images from database by relative address in C#

i have a windows form that contains two tabs . first tab is for save image and second is for retrieve.
Also my source pictures are in my bin project address like this :
C:\Users\BlackRose\Documents\Visual Studio 2012\Projects\RealState\RealState\bin\Debug\HomePics
now I wonder that how I can save address of pictures to sql server and retrieve them even I change my project location ...
I Already try these codes :
string path;
public myForm()
{
path = Environment.CurrentDirectory.ToString() + "\\HomePics";
openFileDialog1.InitialDirectory = path;
}
then write some sql and c# code in a function and save imagePath and imageName that no problem to save them.
but I'm sure I must configure path to set relative path, because the string of path that saved in db is like this :
C:\Users\BlackRose\Documents\Visual Studio 2012\Projects\RealState\RealState\bin\Debug\HomePics\pic1.jpg
with this method, the problem occurs when I want to move my project folder to otherwhere
and all of addresses in db will be useless.
could you tell me any useful method so i can retrieve it in any conditions?
You can use HomePics as folder name while saving the Path into Database as below:
path = "\\HomePics\\pic1.jpg";
while accessing Image Path from Database just Add Below Code:
String strRelativePath=getRelativePathfromDB();//gives you \Home\pic1.jpg
String strAbsoluteFilePath= System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase).Replace("file:\\", "")+strRelativePath;
So finally strAbsoluteFilePath contains below Absolute Path:
C:\Users\BlackRose\Documents\Visual Studio 2012\Projects\RealState\RealState\bin\Debug\HomePics\pic1.jpg
the above path changes the dynamically depending on the location from where you are executing your project.
I hope this solves your problem :)
What you could do is:
Save the relative path in the database, i.e. path relative to \HomePics (root folder) in your example (provided that all files are in that folder and its subfolders).
In the config file of your application, add a setting to say where the root folder is located, e.g. in your <appSettings> you could have an entry <add key="ImagesRootFolder" value="C:\Images\HomePics" />. Alternatively, you could save the same information in the database as well, in a table separate to images.

How to load css into html dynamically?

My C# program uses a web browser control and I programmatically set its html property by laoding it from a html string variable. This almost works well ,but I noticed it lost the reference to the css file. I think a simplest solution is to make the path of the css file absolute,but I want it remains relative to the C# executable.So let me ask how to let the html reference to the css file in such a context.
Thank you in advance.
Edit: I am sorry . My c# application is a desktop one ,although it uses a web browser control.
Edit: Let me put some code. I first load the document from an html file then store it in a variable then for the 2nd time or later I load the document from the variable.
//first load
web_browser_control.Url = new Uri( dir + #"\HTML\default1.html" );
void wB2_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{ html_string = web_browser_control.DocumentText; }
//second load or later
web_browser_control.DocumentText = html_string;
You need to have a look at what path it THINKS its resolving, it would be best if you could please include some code, chances are its not resolving to where you think it is as its executing out of the bin directory (is your path correct relative to the path of the executable and the html),
For example is the html its looking at still where you think it is or is it now in a different directory so the relative paths are now obsolete ?
More code would be good and an indication of the control you are using.
Seems you can change property of css file to be "content" and make property "copy to output directory" - "always", so the wep app dll will be in the same directory with css file.
Or you can use MapPath method.

C# Absolute URI removes ".." from URL

I have to upload a file via FTP to ftp://ftp.remoteServer.com
My root directory on remoteServer contains an "upload" and a "download" folder. I need to put my file in the "upload" directory. But on log in, the server automatically puts me in the "download" folder.
I tried doing this:
string serverTarget = "ftp://ftp.remoteServer.com/";
serverTarget += "../upload/myfile.txt";
Uri target = new Uri(serverTarget);
FTPWebRequest ftp = (FTPWebRequest)FtpWebRequest.Create(target);
using(Stream requestStream = ftp.GetRequestStream()) {
// Do upload here
}
This code fails with: (550) File unavailable (e.g., file not found, no access)
I debugged the code, and target.AbsoluteUri returns as ftp://ftp.remoteServer.com/upload instead of ftp://ftp.remoteServer.com/../upload (missing the ..)
If I put ftp://ftp.remoteServer.com/../upload in a browser, I can log in and verify this is the correct place where I want to put my file.
How can I get the FTPWebRequest to go to the correct place?
I believe you can encode the dots as %2E to keep the dots in your URI.
So something like:
string serverTarget = "ftp://ftp.remoteServer.com/%2E%2E/upload/myfile.txt";
Try this:
string serverTarget = "../upload/myfile.txt";
Uri uri = new Uri(serverTarget, UriKind.Relative);
Andy Evans' comment is correct.
Consider the URI: http://ftp.myserver.com/../. The .. means, "take me to the parent of this directory". But there is no parent! So when you derive the absolute URL, you're going to end up with http://ftp.myserver.com/ There is nothing else that the parser can do.
I think the problem is with the configuration of your FTP server. I assume that the directory structure looks something like:
ftproot
upload
download
It looks like the FTP service is automatically logging you to /ftproot/download. That is, the URI ftp.myserver.com gets mapped to /ftproot/download on the local file system. If that's the case, no amount of fiddling with the URI is going to get you anywhere. If the URI root is mapped to the download directory, there is no way you can, using the .. syntax, "go up one level and then down."
Are you able to upload using an FTP client such as Filezilla, or perhaps the Windows FTP command line tool? If so, what are the steps you take to do it? Can you make your code do the same thing?

Categories

Resources