I need the same thing as this guy here:
http://forums.asp.net/t/1507682.aspx
The thing is that the answer he marked as correct doesn't work for me. I am using ASP.NET MVC3 soon to be migrated to MVC4 and Windows Server 2012.
I want to prevent direct access to some images because of security issues. It's not Image Leeching protection I'm worried at this moment, I read several articles on how to do that.
If the link is on my page like this
<img src="/Content/Images/img1.jpg" />
The image should be shown, but not if it is directly accessed:
http://mywebsite.com/Content/Images/img1.jpg
Since we're talking about images and several people accessing it, a solution that considers performance issue would be my way to go.
Any ideas on how to implement that?
Thanks.
You probably want to think outside MVC and handle hotlinking in IIS itself. IIS has the tools (the referer (sic) header) to figure out whether or not an image request appears to have come from inside your site or not.
Write an Action method which reads the image from disk / db and render it. In that action method, you may check whether the user is authorized or not and return the appropriate image or a "not authorized" image.
public class ProductController : Controller
{
public ActionResult Photo(string id)
{
// TO DO: get image using the unique id passed and render it
}
}
You can use the path to this action method as your image path.
<img src="#Url.Action("Photo","Product")/someUniqueIDOfPhotoFromYourDB" />
This approach will have a slight performance impact compared to serving image directly from disk.
Related
I am developing a movie library application in asp.net. In admin page, I need to add a movie to the database(details such as name, actors, poster url). And also I need to upload the trailer of the movie to a specific folder in the server.
In my AddMovie View(which is strongly typed to a MovieDetails Model), I have a forms to include movie information as text and with a file input to upload a file(movie trailer). Within my controller I get the binded MovieDetails model and the uploaded file seperately as two parameters as follows.
At first I just posted from my view to this controller without using ajax. I was able to get the Model and the file to the controller to do what I needed to do.
Then I moved to ajax and tried to do this without page refresh.
Now no files cannot be uploaded. I tried to debug and noticed that uploadFile parameter of the controller is null although I attached a file to the file input in the view.
Is there any way to post the model to the controller and upload the file without completely changing the controller and using a single ajax call?
Or else is it possible pass the file path through a model attribute, access that file path and upload the relevant file in the controller, using Ajax.
Thank you!
As Darin mentioned, there is no simple way to handle file-uploading matters via ajax for some security reasons and you can't upload files to your server easily; but good news is there are some tricks which can resolve it, for instance, you can use jquery AjaxForm in your mvc form easily with a bit little modification. Take a look at jquery-ajax-form and its samples, you will get some good idea around it.
Normally you cannot upload files using AJAX. Modern browsers that support FormData would allow you to directly make AJAX requests containing multipart/form-data content. Also look at the native XMLHttpRequest object.
But if you need to support legacy browsers you will need some fallback mechanism such as hidden iframes or Flash movies. Plugins such as blueimp would detect the browser capabilities and upload the file using the best option that the browser supports.
I currently store a number of document preview images (jpg/tif) outside of my web root. There are 100s of them, so having this work efficiently is important.
The reason they are stored outside of the web root is that they contain data the only specific users/user groups may view (but each user can have 100s of documents they can view).
My current implementation is, when the user selects ‘view image’ an ajax call is triggered and this moves the image in question to a specific folder within the web root. The location is passed back and used to display the image to the user.
When the next image is clicked, the call deletes any existing images and copies over the requested image. At session logout / timeout the users image folder is emptied.
This has a few problems, but mainly:
Files are constantly being copied and deleted
There is the risk of images being left in the folder (issues with log off scripts)
The whole time an images is in the folder it could be viewed by another users (unlikely but possible)
Is there a better way of doing this? I looked at trying to combine the BinaryReader with the ajax call (as I hoped this would cut out the need to copy the files), but can’t see how to get the data back to be used by the JS in the calling page.
Alternatively is there a way of making selected Folders only accessible to given users based on some session criteria? (I can’t imagine there is but I thought it’s worth asking.)
So if anyone has any ideas on how this can be improved that would be great.
This is a c# ASP.NET app using Jquery.
Edit:
The image is displayed using ajax, this allows for preloading and also means the rest of the page does not need to be reloaded when they select the next/previous image.
It can almost be thought of as a javascript image swapper type situation, where the images are stored outside of the web root.
Thanks.
My current implementation is, when the user selects ‘view image’ an ajax call is triggered and this moves the image in question to a specific folder within the web root.
This is horrible idea. You realize you can just access the image data and pass it to web as stream with specific mime type, right?
Maybe try to write a method that will check user credentials by cookies, if it is not OK then load and send back some standard image that will say that user must log in to view file, if it is ok then load and show proper file from a path outside of root based on url parameter (with proper headers like content-type also often referred as mime-type ofc). Then link urls to that method with proper parameter(s).
You can easily find examples of code (like here) to display image in binary form from DB. You would need just to load them from some path outside of root, not DB.
Also you don't need to load it by AJAX - just add IMG with SRC pointing to URL of handler. Or redirect / open window if it needs to be downloaded not shown.
The issue was how to get an image to show via javascript that is not in the web root.
I created a generic handler (ashx file) that based on the session values (authentication) and submitted parameters would return an image.
That in turn is being called via AJAX.
Is it possible to derive a location path of an in-memory file?
My justification for doing this is based on having a collection of images that are retrieved by my WinForms application in a Base64 encoded string format. I need to build up some HTML and inject these images so that they can be rendered on an embedded page in a WebBrowser control on my application. Since we're talking about HTML here, I need to use the <IMG> tag to display the image. This element needs to accept a "src" path which means I need to determine a method of deriving an absolute/relative path to each of the in-memory images.
If you control the application running on the server (which you indicated in a comment), then you should be able to redirect requests for particular resources. For example, if the user application requests "http://myserver/memory/imgxxx.jpg", the server should be able to intercept that and, rather than try to serve imgxxx.jpg from disk, construct an image from the data in memory, and ship it down to the client.
Now, if you're just shipping the base64 encoded data to the client, and want the client to somehow access the data and do the conversion ... that's a harder problem. I can envision doing something with JavaScript to replace all of the img tags that have some given attributes with the corresponding image. But I suspect that'd get pretty messy. If it's even possible.
Another possibility is to create a derived WebBrowser component and customize its behavior. A good example is in the CreateSink method documentation. It might be possible to write a handler that is called whenever the component wants to download something. You could then intercept the call and supply your in-memory image. I'm not certain that this is possible. You might take a look at WebBrowser customization. I will say, though, that it's probably easier to just write the files and use a "file://" url.
You can build a light weight HTTP server into your application by using the HttpListener class.
You will want to use the asynchronous model. Create a url that it serves content to, such as "http://*:8080/appdata", and then use that url within your html (http://localhost:8080/appdata/someinmemoryresource").
When theHttpListener receives a request, look at the path and respond with whatever in memory data it is you want to serve!
The IMG tag does not need a path, it needs a URL. You cannot reference in-memory data with a URL. The browser is going to issue a second HTTP request with the URL provided in the IMG tag and that URL must be valid at this point.
Consider adding an MVC action or an HTTP handler to return the image bytes. Or save it to disk.
There something I still do not understand about how the Content folder works in ASP.NET MVC. To make things clearer I have a few questions:
Is the Content folder the root folder? I mean does http://localhost/ point to Content or is it something else?
I have a file named dummyIcon.png inside Content/images/temp folder. How do I locate it from my domain layer (which is a Code Library project)?
What is the best practice of displaying images in ASP.NET MVC? Should I store a path to the image in the database (which I personally prefer), or do I save a byte array and return it to the view?
I found the following links to be helpful within the context of the MVC web application, but I'd still appreciate some answers to the questions posted above. Thank you.
Can an ASP.NET MVC controller return an Image?
how to display image using view and controller by ASP.NET MVC
Anything in the root will point to the root if it is ignored by your routes:
If you have an image placed on the on the root of your project. Then, say http:://localhost/dummy.ico" will give you a 404, no controller found. Until you do this in your global.asax.cs:
routes.IgnoreRoute("dummy.ico");
//you could add wildcards here to match different things
From Code if you use says File.Open(); you need the physical path to the file. You get it like this:
string filePath = Server.MapPath(Url.Content("~/Content/Images/Image.jpg"));
It is upto you here, although I would say, putting files into the database makes a lot of sense if you want everything in one place. If you need to move your app around you would just move the data base.
When it comes to file paths, please remember you don't want duplicate file names, so you will have to give each file a GUID and then link it up. It could make sense if you have a large number of files (or large files itself) so you're database won't grow like crazy.
HTH
1.Is the Content folder the root folder?
I mean does http://localhost/ point to
Content or is it something else?
No, http://localhost:port/ does not point to content folder. You can access files in content folder through http://localhost:port/content/...
2.I have a file named dummyIcon.png
inside Content/images/temp folder. How
do I locate it from my domain layer
(which is a Code Library project)?
You should be able to access it as http://localhost:port/Content/images/temp/dummyIcon.png
3.What is the best practice of
displaying images in ASP.NET MVC?
Should I store a path to the image in
the database (which I personally
prefer), or do I save a byte array and
return it to the view?
Where you store the images depends on your application needs. Are these generic images that is used to display application images (icons, company logo, etc).. Then it is best to store them in file system.
If your application deals with images and you work on storing images, manipulation etc, then you may need DB. I think, storing images used on the web application is a overhead.
You should make a model object for your controller to return. in this example i am returning SearchPageModel, a class i have created. but lets say this object has a property called imageURL
but make sure the controller actually returns an ActionResult
so for example...
[AcceptVerbs(HttpVerbs.Get)]
public ActionResult Search()
{
SearchPageModel Model = new SearchPageModel();
// populate the Model properties
Model.ImageURL = "myjpeg"
return View("Search", Model);
}
i then pass this model object back to my desired view in this case my "Search" View
and to display the image, in the view i would add..
<img src="Images/<%=Model.ImageURL %>.jpg" />
I am creating a site whose content is dynamic and has images in it.
What/How much performance hit will my DB (MSSQL) take if I save content/Images in DB?
I am just trying to understand what kind of problems I may run into.
I appreciate any responses.
Thanks!
If you keep content (e.g. images) outside of the database, you can let IIS serve this content directly without calling ASP.NET at all (and as a consequence, no database access is needed).
You can even put static content on a different server is you have huge load (like here on StackOverflow).
So if you need to scale in any way, keep static content outside of both ASP.NET and database.
In the company where I'm employed we are using a custom-made CMS.
It renders content and controls for a page dynamically. The content are stored in a table for all pages, (each page has one main content), and other tables store information regarding UserControls, path to it, and which properties should be set with which value via reflection.
The performance is good, even for lets say 10 dynamically created controls. Our biggest client's page has about 70k hits a day and there is no performance problem. The page renders really fast.
Storing the images in your database can also work.
Just keep in mind that you need to use server-side caching for your images (e.g. get them via a generic handler *.ashx and use chaching there) and hope that your imageurl gets recognized for clientside caching.
If you want to be sure, expose your images directly on a dedicated image application. (e.g. www.foobar.com is your URL, then you can create images.foobar.com and store all your images there)
If would definetly advise to store often used images there, like images for the layout, or userpictures (if you are using a forum, or some kind of web application that uses several pictures all the time). But there is nothing wrong with storing not often used pictures in the database (user related uploads et cetera).
If you store your images in DB, database size will increase and this will result in slower DB queries. Better store on other media and guide your DB to do the stuff for you.