Reputation: 7164
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
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
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.
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.
Directory.GetFiles
method has an overload which takes a search pattern. You may consider using that and totally get rid of the foreach
loop./images/file.jpg
) , IIS will serve the file (without executing any MVC code. That will be faster).Upvotes: 1