jason
jason

Reputation: 7164

How to get a file without knowing its extension - ASP.NET MVC

There is a file in folder "Images" in server.

The file's name is "jason", but I don't know if it is "jason.pdf" or "jason.jpg" or "jason.png".. However the file must have one of these extensions : ".pdf, .png, .jpg". There is no other option.

I know I can get the file like this if I know its extension is ".pdf" :

<a href="~/Images/jason.pdf">File</a>

But I don't know what to do if I don't know its extension. How can I get the file without knowing its extension but knowing only file name? Thanks in advance.

Upvotes: 1

Views: 1240

Answers (1)

Shyju
Shyju

Reputation: 218752

You may consider creating an controller action which serves you these files.

Here is a quick-working-simple example. Feel free to edit it to make it ophisticated & robust as needed.

public class ImageController:Controller
{
    private string GetFilePath(string fileName)
    {
        var path = Server.MapPath(Url.Content("~/Images"));
        //Getting all the files present in this directory
        var files = Directory.GetFiles(path);

        // Loop through each items(filenames) and  check the filename(without extension)
        // is matching with our method parameter value
        foreach(var file in files)
        {
            if(Path.GetFileNameWithoutExtension(file)
                   .Equals(fileName,StringComparison.OrdinalIgnoreCase))
            {
                return file;
            }
        }
        return string.Empty;
    }
    [Route("image/{fileName}")]
    public ActionResult GetFile(string fileName)
    {
        var path = GetFilePath(fileName);
        // to do : handle if path is string.empty
        // may be return default content/file ?
        var contentType = MimeMapping.GetMimeMapping(path);
        byte[] bytes = System.IO.File.ReadAllBytes(path);
        return File(bytes, contentType);
    }
}

Now in your other view, you will call this as

<a href="~/Image/jason">PDF File</a>

Or

 <a href="~/Image/puppy">Image file name</a>

Here we are using attribute routing for our method so that the request to /image/{filename} will be mapped to the GetFile method. Make sure you have attribute routing enabled by calling MapMvcAttributeRoutes method inside RegisterRoutes method of RouteConfig.cs.

public class RouteConfig
{
    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");                    
        routes.MapMvcAttributeRoutes();

        //Existing default route defnition goes here           
    }
}

Few things to consider

  1. The above simple implementation is reading all the files in the Images directory every time the action method is invoked. You should consider caching the results(list of file names, return value of GetFiles) so that you can avoid making the call all the time. You can store it in an in memory cache/ database etc.

  2. If user is passing a file name which does not exist in the location, what do you want to return. The GetFilePath method above returns string.empty in that case. Handle it inside the GetFile method.

  3. The Directory.GetFiles method has an overload which takes a search pattern. You may consider using that and totally get rid of the foreach loop.
  4. If you are serving static file (ex :/images/file.jpg) , IIS will serve the file (without executing any MVC code. That will be faster).
  5. Explore caching options and see how that can make your experience even faster.

Upvotes: 1

Related Questions