skip to Main Content

I have got images on the web server like {sku_number}.jpg. Now I would like to have for every visitor a filename for this image like {sku_number}foo.jpg without renaming the files on the web server.

Is this possible and how?

4

Answers


  1. If i understood you properly then one of the options would be HTTP Handler

    public class ImageHttpHandler : IHttpHandler
    {
       
        public bool IsReusable
        {
            get { return false; }
        }
        protected RequestContext RequestContext { get; set; }
    
        public void ProcessRequest(HttpContext context)
        {
            AdvertType type;
            var url = context.Request.Url.ToString();
            //TODO: get ID and extension from url 123456789_TitleOfTheProduct.jpg
            var path = "yourpathtoimgfolder/id.extension"
            //Get binary data
    
            context.Response.ContentType = "image/png";
            context.Response.BinaryWrite(bytes);
        }
    }
    

    Then register it in web.config in system.webServer -> handlers

     <add name="YourName" verb="*" path="virtual/folder/*" type="Namespace.ImageHttpHandler, Your.Assembly.With.Handler, Version=1.0.0.0, Culture=neutral" preCondition="managedHandler" />
    
    Login or Signup to reply.
  2. Reference

    Url.Content helper method takes a virtual content path to your file and returns a url to access the file in your site. You should not be passing a physical directory location to that.

    You may consider saving the images in your web app. Create a directory called “Images” and then you can safely use Url.Content method.

    For example,

    @foreach (var imgPath in Directory.GetFiles(Server.MapPath(Url.Content("~/Images/"))))
    {
        <img src="@Url.Content("~/Images/"+ @Path.GetFileName(imgPath))" />
    }
    

    Or If you absolutely need to store the images somewhere outside the app root,(Ex : “C:tempimages or a network location), You might consider creating an action method which takes the file name, read the file from the location and return as an image.

    public ActionResult GetImg(string id)
    {
        var path = $@"C:tempimages{id}.png";
        var bytes = System.IO.File.ReadAllBytes(path);
        return File(bytes, "image/png");
    }
    

    Now you simply need to call this end point and use that as the image src property.

    @foreach (var imgPath in Directory.GetFiles(@"C:tempimages", "*.*"))
    {
        <img src="@Url.Action("GetImg",new {id=Path.GetFileNameWithoutExtension(imgPath)})" />
    }
    

    The above is a simple solution where i hard coded it to return png files. you can update it to be more flexible (add a param to accept the file extension as well)

    Note : I personally prefer to keep minimal C# in razor files. I like to move the C# code (all those Directory.GetFiles lines) to the GET action and pass the list of image names to the view via a view model/view bag(as needed).

    Login or Signup to reply.
  3. You can create a simple controller to handle such requests.

    [RoutePrefix("products/images")]
    public class ProductImagesController : Controller {
        [HttpGet]
        [Route("{sku_number:long}_{title}.{extension}", Name = "ProductSkuImage")]//Matches GET products/images/123456789_TitleOfTheProduct.jpg
        public ActionResult Get(long sku_number, string title, string extension) {
            var fileStorePath = Server.MapPath("~/images");
            var fileName = string.Format("{0}.{1}", sku_number, extension);
            var path = Path.Combine(fileStorePath, fileName);
            if (System.IO.File.Exists(path)) {
                var mimeType = MimeMapping.GetMimeMapping(fileName);
                var downloadName = string.Format("{0}_{1}.{2}",sku_number,title,extension);
                return File(path, mimeType, downloadName);
            }
            return HttpNotFound();
        }
    }
    

    Just meant as a simple self explanatory example, the above can be refactored to allow more flexibility. For example instead of loading file from disk the sku could be used to get the file from another data store like a database or web service.

    Example of calling from View

    <a href="@Url.RoutUrl("ProductSkuImage", new { sku_number=123456789 , title = "TitleOfTheProduct" , extension="jpg" })" >TitleOfTheProduct</a>
    

    would generate

    <a href="http://localhost/products/images/123456789_TitleOfTheProduct.jpg">TitleOfTheProduct</a>    
    
    Login or Signup to reply.
  4. I would recommend returning a 302 from the spoofed image to the original image, it’ll allow your web server to still properly cache the asset without you doing really inefficient reads/writes off of the file system every time the asset is requested at the .NET level, while still masking the paths in the DOM with the spoofed paths (though the original paths will be visible if that’s a problem).

    Verify that the 302 is going to work for your specific needs though.

    Otherwise you’ll want to basically emulate the IIS pipeline for asset caching and that can be rough.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search