Posts Tagged ‘output response’
Say a file has a physical filename of ‘xyz.pdf’, but when you send it to the user you want it to have a name like ‘myxyzbrilliantfilename.pdf’. How do you change the target filename when transmitting files through the output stream of Response without it popping up a download dialog?
I have searched wide and wild and the only way you could do this is by modifying the “ContentDisposition” like so:
Response.AddHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");
// OR
Response.AddHeader("Content-Disposition", "inline; filename=\"" + fileName + "\"");
The “attachment” setting opens a dialog to save the file with the correct name and the “inline” setting doesnt open a dialog, but ignores the filename!
This is not the behaviour I am looking for, so I had a quick coffee and came up with the following very simple solution!
My solution came in the form of a new route in my mappings:
routes.MapRoute(
"ResourceModulePdf", // Route name
"ResourceModule/Pdf/{id}.pdf", // URL with parameters
new
{
controller = "ResourceModule",
action = "Pdf",
id = "",
sourceFilename = ""
} // Parameter defaults
);
and my ‘pdf’ action:
public ActionResult Pdf(string id, string sourceFilename)
{
// We do not need to do anything with 'id'. It has served it's purpose already
return new FileResult(sourceFilename, "application/pdf");
}
… and my FileResult
public class FileResult : ActionResult
{
public String ContentType { get; set; }
public byte[] ImageBytes { get; set; }
public String SourceFilename { get; set; }
//This is used for times where you have a physical location
public FileResult(String sourceFilename, String contentType)
{
SourceFilename = sourceFilename;
ContentType = contentType;
}
//This is used for when you have the actual image in byte form
// which is more important for this post.
public FileResult(byte[] sourceStream, String contentType)
{
ImageBytes = sourceStream;
ContentType = contentType;
}
public override void ExecuteResult(ControllerContext context)
{
var response = context.HttpContext.Response;
response.Clear();
response.Cache.SetCacheability(HttpCacheability.NoCache);
response.ContentType = ContentType;
if (ImageBytes != null)
{
var stream = new MemoryStream(ImageBytes);
stream.WriteTo(response.OutputStream);
stream.Dispose();
}
else
response.TransmitFile(SourceFilename);
}
}
All we need to do now is construct our hyperlinks like so:
Doc
By default the “TransmitFile” method will take the name of the filename you used in your hyperlink and the result is exactly what we wanted!