Asp.Net MVC ActionResult with File - asp.net-mvc

In Asp.Net MVC, we need to show a Html page, but also when that page shows, download a file too as the result of a form post.
Is there a kind of ActionResult that both renders HTML, but also cause the browser to download a file? Think of a page that shows "Here's your requested file" and the file starts to download.
Basically a combination of ActionResult and FileResult in one.

Here's a controller example that returns a file. I added an Iframe to the view that targets the controller method. I set the hidden attribute so the iframe doesn't show anywhere in the page. Hope you can use the solution. It seems to work very smoothly.
[HttpGet]
public FileResult GetPDF()
{
string fileName = "test.pdf";
string filePath = HttpContext.Server.MapPath(string.Format("~/Content/{0}", fileName));
byte[] fileBytes = System.IO.File.ReadAllBytes(filePath);
return File(fileBytes, System.Net.Mime.MediaTypeNames.Application.Octet, fileName);
}
Add the following code to your view.
<iframe hidden="hidden" src="#Url.Content("~/Home/Home/GetPDF")"></iframe>

Related

.Net MVC returning a File

I'm working a Controller that will generate/retrieve files. These will optionally set headers.
public IActionResult SampleFileReport()
{
I see the return type is IActionResult (a data contract). I see inside the function I can still set
response.ContentType
Is there a preferred pattern for how to set ContentType in a controller?
I'm thinking it should be part of the DataContract and setting response.contentype is an anti-pattern, however I see examples such as this that utilize it. Returning a file to View/Download in ASP.NET MVC
All you need to do is return File:
public IActionResult SampleFileReport()
{
// do stuff
return File(bytes, mimetype, filename);
}
File also has overloads that accept Stream and string (path and filename to a file on the filesystem) in addition to byte[]. The mimetype is your content type, e.g. application/pdf, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet (Excel), etc. The final filename param is optional. If it's provided, a Content-Disposition: attachment header is sent with the response, which prompts the browser to pop a download dialog. Otherwise, the default Content-Disposition: inline is used, and the browser will try to load the returned file directly the browser tab/window, assuming the mime-type is supported for native rendering the browser. If not, then you'll get a download dialog, regardless.
If we are talking about MVC (not .NET Core) then you can change IActionResult to FileContentResult
public FileContentResult SampleFileReport()
{
byte[] fileBytes = GetFileBytes();
return File(fileBytes, MediaTypeNames.Application.Octet, "fileName");
}
Just checked this class still exists. FileContentResult .NET Core

Can i download a pdf file saved in media in Umbraco

I need to set create a page on which i have button and on clicking, it should redirect to a registration page and then download a pdf file. so i created a document type in Umbraco which have a file Upload field and i uploaded one file through it. On its template i have added a macro which have a partial view for the registration page. After completing registration, this pdf file should download automatically.
My problem is, the file i uploaded is not showing in the Media library. but the Url is as follows: /media/1051/filname.pdf .
am getting this url in controller. but couldn't get the file usinng its id.
[HttpPost]
public HttpResponseMessage DownloadFile([FromBody] DownloadEBookViewModel model)
{
int id = Convert.ToInt32(model.Url.Split('/')[2]);
var media = Umbraco.Media(id).Url;
if (!File.Exists(media))
throw new HttpResponseException(HttpStatusCode.NotFound);
HttpResponseMessage Response = new HttpResponseMessage(HttpStatusCode.OK);
byte[] fileData = File.ReadAllBytes(media);
if (fileData == null)
throw new HttpResponseException(HttpStatusCode.NotFound);
Response.Content = new ByteArrayContent(fileData);
Response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
return Response;
}
Someone please help. thank you
When working with the Umbraco helper in code behind, I would advise to use the typed variants for getting items
var media = Umbraco.TypedMedia(id).Url;
This will give you a strongly typed model with intellisense
To get the physical file from the media object you'll probably want to call
byte[] fileData = File.ReadAllBytes(media.getPropertyValue("umbracoFile"));
instead of:
byte[] fileData = File.ReadAllBytes(media);
(code is untested)

MVC - FileContentResult sends corrupted pdf

I have a simple action method that returns a PDF document, that gets shown in an <iframe> with an <embed> tag, and every few calls to this method will return a corrupted PDF. (I've determined its corrupted by using dev tools to save the response from the server)
Action Method:
public FileContentResult GetPdfReport(string Id)
{
Response.AppendHeader("Content-Disposition", "inline; filename=report.pdf");
var content = System.IO.File.ReadAllBytes(Server.MapPath("~/Reports/Testfile.pdf"));
System.IO.File.WriteAllBytes(Server.MapPath("~/Reports/debugReport.pdf"), content);
return File(content, "application/pdf");
}
View Content:
<embed id="widgetResponsePdf" src="#Url.Action("GetPdfReport", "WidgetResponse", new { Id = "123" })" type="application/pdf" onmouseout="mouseOutHandler();" />
The files TestFile.pdf and debugReport.pdf open just fine when I get a corrupted PDF, and there is no difference in the request and response header between the normal request/response and the corrupted request/response.
Is there some setting in IIS that I am missing that could be causing the inconsistent behavior between requests, or could this be caused solely by a network issue?
In our case, the IFrame has a src attribute that points to a partial view that loads the <embed> content, which then has a src attribute that points to the actual PDF file instead of a PartialView that returns a FileContentResult. The example below has been simplified from our actual implementation
Partial View
<iframe> <!-- iframe is actually loaded from another partial view, it is show here to simplify things -->
<embed
src='#Url.Content(Model.ReportFileName)'
type="application/pdf">
</embed>
</iframe>
Controller
public PartialView GetPdfReport(string Id)
{
var model = PDFResponseModel
{
ReportFileName = Server.MapPath("~/Reports/Testfile.pdf")
};
return PartialView(model);
}
Due to a site restriction for IE support, our users (intranet site) are required to have AdobeAcrobat installed to view PDF's. While this solution works for us, this may not be desirable for internet facing websites.

How to show a pdf file in the browser tab from an action method

I'm trying to do pdf viewer functionality in mvc application. When user click the "read the pdf" link it should open a new tab/window and user should be able view the pdf file. So I checked the examples but I couldn't find. Could you suggest me any article or example ?
Show an anchor tag in your first view and pass an id (to identify what PDF to show)
#Html.ActionLink("read the pdf","view","doc",new { #id=123},null)
Now in the doc controller, have an action method which have a parameter called id and return the pdf there using the File method.
public ActionResult View(int id)
{
byte[] byteArrayOfFile=GetFieInByteArrayFormatFromId(id);
return File(byteArrayOfFile,"application/pdf");
}
Assuming GetFileInByteArrayFormatFromId is the method which returns the byte array format of the PDF file.
You can also return the PDF if you know the full path to the PDF file physically stored, using this overload.
public ActionResult Show()
{
string path="FullPAthTosomePDFfile.pdf";
return File(path, "application/pdf","someFriendlyName.pdf");
}
Show the PDF in a browser without downloading it
Based on the browser setting of the end user, the above solution will either ask user whether he/she wishes to download or open the file or simply download/open the file. If you prefer to show the file content directly in the browser without it gets downloaded to the user's computer, you may send a filestream to the browser.
public ActionResult Show(int id)
{
// to do : Using the id passed in,build the path to your pdf file
var pathToTheFile=Server.MapPath("~/Content/Downloads/sampleFile.pdf");
var fileStream = new FileStream(pathToTheFile,
FileMode.Open,
FileAccess.Read
);
return new FileStreamResult(fileStream, "application/pdf");
}
The above code expects you to have a pdf file named sampleFile.pdf in ~/Content/Downloads/ location. If you store the file(s) with a different name/naming convention, you may update the code to build the unique file name/path from the Id passed in.
If you want to display the PDF Content in browser, you can use iTextShare dll.
Refer the link http://www.codeproject.com/Tips/387327/Convert-PDF-file-content-into-string-using-Csharp.
Reading PDF content with itextsharp dll in VB.NET or C#

What is the MVC way of simultaneously sending a file and redirecting to a new page?

I have a form which users must fill out and submit. The controller action does some work and decides the user can have a file and so redirects to another action which is a FilePathResult.
[CaptchaValidator]
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Index(FormCollection collection)
{
// do some stuff ...
return RedirectToAction("Download");
}
[AcceptVerbs(HttpVerbs.Get)]
public FilePathResult Download()
{
var fileName = "c:\foo.exe";
return File(fileName, "application/octet-stream", "installer.exe");
}
What I would like to do is redirect the user to another page which thanks the user for downloading the file but I'm not sure how to accomplish that in a "MVC-like" way.
The only way I can think of off the top of my head is to skip the Download action and instead redirect to the ThankYou action, and have the ThankYou view use javascript to send the file. But this just doesn't seem very MVC to me. Is there a better approach?
Results:
The accepted answer is correct enough but I wanted to show I implemented it.
The Index action changes where it redirects to:
return RedirectToAction("Thankyou");
I added this controller (and view) to show the user any "post download information" and to say thanks for downloading the file. The AutoRefresh attribute I grabbed from link text which shows some other excellent uses.
[AutoRefresh(ControllerName="Download", ActionName="GetFile", DurationInSeconds=3)]
[AcceptVerbs(HttpVerbs.Get)]
public ActionResult Thankyou()
{
return View();
}
The action which get redirected to is this same as it was before:
[AcceptVerbs(HttpVerbs.Get)]
public FilePathResult GetFile()
{
var fileName = "c:\foo.exe";
return File(fileName, "application/octet-stream", "installer.exe");
}
Just add a header to your response, in the action for your redirected page.
Googling came up with this header:
Refresh: 5; URL=http://host/path
In your case the URL would be replaced with the URL to your download action
As the page I was reading says, the number 5 is the number of seconds to wait before "refreshing" to the url.
With the file being a download, it shouldn't move you off your nice redirect page :)

Resources