Response.TransmitFile does not work in mvc 5 - c#

I have a mvc 5 application, I save letters files in folder inside folder like (~\Files\Letters) and I save the physical path in database, uploading letters files to (~\Files\Letters) works fine and saving the physical path works fine, the problem is downloading a letter file to client machine, I have tried using Webclient and Response both don't work and don't give any error, here is the code for downloading a letter file using Response.
[HttpPost]
public void open(int id)
{
string path = "";
path = db.tblLetters.Where(t => t.ID == id).SingleOrDefault().LetterImg;
string fileName = path.Substring(path.LastIndexOf(#"\")+1);
string p = Server.MapPath("~/Files/LettersImgs/" + fileName);
Response.Clear();
Response.AddHeader("content-disposition", "attachment; filename=" + fileName);
Response.ContentType = "application/octet-stream";
Response.TransmitFile(p);
Response.End();
}

Rather than using old-style Response.TransmitFile, you can use FilePathResult to return file directly from server's file path. Change return type from void to ActionResult (or FileResult) and use [HttpGet] instead of [HttpPost], and do return File(...) to let user download the file like this example below:
[HttpGet]
public ActionResult Open(int id)
{
string path = "";
path = db.tblLetters.Where(t => t.ID == id).SingleOrDefault().LetterImg;
string fileName = path.Substring(path.LastIndexOf(#"\")+1);
string p = Server.MapPath("~/Files/LettersImgs/" + fileName);
return File(p, "application/octet-stream", fileName);
}
Related issue: How to download a file to client from server?

Related

Issue of Set Download File name from controller MVC Core

I tried to get and download file from server local folder to client side. But When I tried to download(also download operation is successfully), Downloaded file's name is set automatically Action Name. How can I change downloaded file name ?
MyController:
[HttpGet]
public PhysicalFileResult MYACTIONDOWNLOAD(string filePathAndName)
{
string downloadPath = Path.Combine(Directory.GetCurrentDirectory(), #"C:\", filePathAndName);
string filesMimeType = MimeTypesMap.GetMimeType(filePathAndName);
return new PhysicalFileResult(downloadPath, filesMimeType);
}
client side(view script):
<a target="_blank" href="(my website www root url)/MYPROJECTNAME/MYCONTROLLERNAME/MYACTIONDOWNLOAD?filePathAndName=\\192.168.X.X\MYREMOTEDISC-1\MYDOCUMENTS\SCHOOL\10012021_1023350.docx"></a>
when I clicked download operation is okey but downloaded file name is MYACTIONDOWNLOAD.docx
I want to change file name.
You can just change your code like following:
return new PhysicalFileResult(downloadPath, filesMimeType) { FileDownloadName = "Test.doc"};
You can try this method instead.
[HttpGet]
public async Task<IActionResult> Download(string path)
{
var memory = new MemoryStream();
string webRootPath = _HostEnvironment.WebRootPath;
var uploads = Path.Combine(webRootPath + path);
using (var stream = new FileStream(uploads, FileMode.Open))
{
await stream.CopyToAsync(memory);
}
memory.Position = 0;
var ext = Path.GetExtension(uploads).ToLowerInvariant();
return File(memory, "application/octet-stream", "any file name");
}
_HostEnvironment.WebRootPath will be give the absolute path of the server. If that comes from your URL then you can avoid this.
Instaed of path use
var bytes = File.ReadAllBytes("your path" )
and then
return File(bytes, mimetype,"name you want" );

Return file not working when to download images from binary data in ASP.net MVC controller

I want to download a .png file but this code is not working for me. This action method is called by a button from partial View.
This is working only when I provide a .pdf file name but not working for images.
public ActionResult Download(string DownloadsID)
{
var lst = (from a in doclst
where a.Id == DataId
select new
{
a.DocName,
a.DocFile,
}).FirstOrDefault();
Response.Clear();
Response.ClearHeaders();
Response.AddHeader("Content-Disposition", "attachment; filename=MyImage.png");
return File(lst.DocFile, "image/png");
}

ASHX Handler not working correctly with clients outside my network

I have an application that is used by people inside and outside my organization. This application exports both Excel (.xlsx) and PDF files. I'm having trouble with the file exports. It works fine for people that are on my network, but people outside my network are getting a "File read error. File type is unsupported or the file is corrupted", and the file will only be 127 bytes instead of it's correct size (normally about 2 megabytes). I need people outside my network to be able to successfully download and open the files.
I've also tried running handler classes tailored to each specific file type, I've tried opening up the directory with the file to let "Everyone" have read access, I'm really not sure on how to fix this. The web server is running IIS 10.
public class fileExportHandler : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
string fileToExport = "";
string fileName = "exportedFile";
string fileType = "";
System.Web.HttpRequest request = System.Web.HttpContext.Current.Request;
if ((request.QueryString["fileToExport"] != null))
{
fileToExport = request.QueryString["fileToExport"].ToString();
string[] fileParts = fileToExport.Split('.');
fileType = fileParts[1];
if ((request.QueryString["fileName"] != null))
{
fileName = request.QueryString["fileName"].ToString();
}
}
fileToExport = #"E:\Website\Cascade\" + fileToExport;
//send the file to the browser
System.Web.HttpResponse Response = System.Web.HttpContext.Current.Response;
Response.ClearHeaders();
Response.Clear();
Response.Buffer = true;
string contentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
if(fileType == "pdf")
contentType = "application/pdf";
Response.ContentType = contentType;
Response.AddHeader("content-disposition", "attachment; filename=" + fileName + "." + fileType);
Response.TransmitFile(fileToExport);
Response.Flush();
HttpContext.Current.ApplicationInstance.CompleteRequest();
}
public bool IsReusable
{
get
{
return false;
}
}
}
Got it figured out. It was a network issue, my network people had moved me to a new server, and people outside my organization were seeing the old server, but people inside were seeing the new version. I got them to get the people outside my organization to see the new server, and that resolved my issue.

Issues when downloading PDF file from MVC application

I have created a function where a user can download a pdf file from my webpage. The file is stored in a databse and is requested from a webapi. The return value of the webapi is a byte[].
My issue here is that when i run the web application on my local iis this function runs without any errors. I get the pdf file and it is downloaded correctly on my machine. But when i deploy the web application to my Test server this code generates either RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION in chrome with some of the files where as other files are downloaded to the machine but when i try to open the pdf file i get: could not load the pdf file.
This happens with both chrome and IE.
This is my code:
[HttpGet]
[DoNotChangeCacheSettings]
public virtual FileResult DownloadTranslationFile(Guid id)
{
Guid assessmentTemplateId = id;
File translationFile = Services.GetFileContent(assessmentTemplateId);
var fileName = HttpUtility.UrlPathEncode(translationFile.FileName);
this.HttpContext.Response.Headers.Add("Content-Disposition", "attachment; filename=\"" + fileName + "\"");
var result = File(translationFile.FileContent.Content, System.Net.Mime.MediaTypeNames.Application.Pdf, fileName);
return result;
}
I have been trying to fix this issue for 2 days now but i simply cant figure out what the issue is. Hope you guys can help. Thanks.
You don't need to use Content-Disposition. .Net will add it for you. From the docs.
The fileDownloadName parameter is used to generate the
content-disposition header. The result object that is prepared by this
method is written to the response by the ASP.NET MVC framework when
the object is executed. The MediaTypeNames class can be used to get
the MIME type for a specific file name extension.
I tend to use the Stream-overload:
[HttpGet]
[DoNotChangeCacheSettings]
public virtual FileResult DownloadTranslationFile(Guid id)
{
Guid assessmentTemplateId = id;
File translationFile = Services.GetFileContent(assessmentTemplateId);
var fileName = HttpUtility.UrlPathEncode(translationFile.FileName);
var stream = = new MemoryStream(translationFile.FileContent.Content);
return File(stream, "application/pdf", fileName);
}
But you can use the byte[] as well:
[HttpGet]
[DoNotChangeCacheSettings]
public virtual FileResult DownloadTranslationFile(Guid id)
{
Guid assessmentTemplateId = id;
File translationFile = Services.GetFileContent(assessmentTemplateId);
var fileName = HttpUtility.UrlPathEncode(translationFile.FileName);
return File(translationFile.FileContent.Content, "application/pdf", fileName);
}
EDIT:
If you got an error when opening the PDF you can ensure that the web browser is doing the right thing by manually saving the PDF from code as well. If that file has errors as well you're probably generating an incorrect byte[].
[HttpGet]
[DoNotChangeCacheSettings]
public virtual FileResult DownloadTranslationFile(Guid id)
{
Guid assessmentTemplateId = id;
File translationFile = Services.GetFileContent(assessmentTemplateId);
var fileName = HttpUtility.UrlPathEncode(translationFile.FileName);
var stream = = new MemoryStream(translationFile.FileContent.Content);
// Code for debugging
var tempDir = "C:\\temp"; // Make sure app pool can write here.
var path = Path.Combine(tempDir, fileName); // Possibly add extension here.
using (var fileStream = File.Create(path))
{
stream.Seek(0, SeekOrigin.Begin);
stream.CopyTo(fileStream);
}
stream.Seek(0, SeekOrigin.Begin);
// Return to client.
return File(stream, "application/pdf", fileName);
}

How can I open a pdf file directly in my browser?

I would like to view a PDF file directly in my browser. I know this question is already asked but I haven't found a solution that works for me.
Here is my action's controller code so far:
public ActionResult GetPdf(string fileName)
{
string filePath = "~/Content/files/" + fileName;
return File(filePath, "application/pdf", fileName);
}
Here is my view:
#{
doc = "Mode_d'emploi.pdf";
}
<p>#Html.ActionLink(UserResource.DocumentationLink, "GetPdf", "General", new { fileName = doc }, null)</p>
When I mouse hover the link here is the link:
The problem with my code is that the pdf file is not viewed in the browser but I get a message asking me if I wand to open or save the file.
I know it is possible and my browser support it because I already test it with another website allowing me to view pdf directly in my browser.
For example, here is the link when I mouse hover a link (on another website):
As you can see there is a difference in the generated link. I don't know if this is useful.
Any idea how can I view my pdf directly in the browser?
The reason you're getting a message asking you to open or save the file is that you're specifying a filename. If you don't specify the filename the PDF file will be opened in your browser.
So, all you need to do is to change your action to this:
public ActionResult GetPdf(string fileName)
{
string filePath = "~/Content/files/" + fileName;
return File(filePath, "application/pdf");
}
Or, if you need to specify a filename you'll have to do it this way:
public ActionResult GetPdf(string fileName)
{
string filePath = "~/Content/files/" + fileName;
Response.AddHeader("Content-Disposition", "inline; filename=" + fileName);
return File(filePath, "application/pdf");
}
Instead of returning a File, try returning a FileStreamResult
public ActionResult GetPdf(string fileName)
{
var fileStream = new FileStream("~/Content/files/" + fileName,
FileMode.Open,
FileAccess.Read
);
var fsResult = new FileStreamResult(fileStream, "application/pdf");
return fsResult;
}
Change your code to this :
Response.AppendHeader("Content-Disposition","inline;filename=xxxx.pdf");
return File(filePath, "application/pdf");
If you read the file stored in database image column, you can use like this:
public ActionResult DownloadFile(int id)
{
using (var db = new DbContext())
{
var data =
db.Documents.FirstOrDefault(m => m.ID == id);
if (data == null) return HttpNotFound();
Response.AppendHeader("content-disposition", "inline; filename=filename.pdf");
return new FileStreamResult(new MemoryStream(data.Fisier.ToArray()), "application/pdf");
}
}
If you are using Rotativa package to generate PDF, Then don't put a name to file with FileName attribute like below example.
return new PartialViewAsPdf("_JcPdfGenerator", pdfModel);
Hope this is helpful to someone.
Although previous posts are often correct; I think most of them are not best practice!
I'd like to suggest to change action return types to FileContentResult and usereturn new FileContentResult(fileContent, "application/pdf"); at the end of action body.
Yes You Can do It Simply by redirecting . it ends extension like u need , .pdf ..
protected void OpenPdfPdf_Click(object sender, EventArgs e)
{
Response.Redirect("jun.pdf");
}
Or another Method ,its opens like .aspx page--
protected void OpenPdf_Click(object sender, EventArgs e)
{
string path = Server.MapPath("jun.pdf");
//or you want to load from url change path to
//string path="https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf";
WebClient client = new WebClient();
Byte[] buffer = client.DownloadData(path);
if (buffer != null)
{
Response.ContentType = "application/pdf";
Response.AddHeader("content-length", buffer.Length.ToString());
Response.BinaryWrite(buffer);
}
}

Categories