Save dialog prompt for PDF instead of saving to hardcoded path - c#

I have successfully implemented the iTextSharp.text.pdf to populate a PDF template file we have setup. Currently that file is being save automatically to a specific folder on local machine...but we don't want that, we want the populated PDF to be saved by the user to the folder of their choice on their pc. We do not want to keep any of these files on the server once this application gets published.
the below code creates the hardcoded file path and it is populated, but the portion at the bottom that prompts the user to save the file, creates a pdf with the file name format we want, but the file is always 20k and wont open. How can I change the below code to not actually create the file on the server, but to create it to the users pc when they chose to save it?
using (FileStream outfile = new FileStream(outputfile, FileMode.Create))
{
PdfReader rdr = new PdfReader(pdftemplate);
PdfStamper stm = new PdfStamper(rdr, outfile);
AcroFields fields = stm.AcroFields;
foreach (var de in rdr.AcroFields.Fields)
{
if (de.Key == "Date")
{
fields.SetField("Date", dt.Rows[0]["Form Date"].ToString());
}
if (de.Key == "Project Name")
{
fields.SetField("Project Name", dt.Rows[0]["Project Name"].ToString());
}
if (de.Key == "Contract No")
{
fields.SetField("Contract No", dt.Rows[0]["Contract Number"].ToString());
}
}
stm.Close();
rdr.Close();
Response.ContentType = "application/pdf";
Response.AddHeader("content-disposition", "attachment; filename=" + newFile);
Response.Write(outfile);
Response.End();
}

I think the problem with your code is that you are using filestream which is causing the pdf to be saved to your server. Using memorystream should fix this. Try something like this and see if it helps.
Using (MemoryStream ms = new MemoryStream())
{
PdfReader rdr = new PdfReader(pdftemplate);
PdfStamper stm = new PdfStamper(rdr, ms);
AcroFields fields = stm.AcroFields;
foreach (var de in rdr.AcroFields.Fields)
{
if (de.Key == "Date")
{ fields.SetField("Date", dt.Rows[0]["Form Date"].ToString()); }
if (de.Key == "Project Name")
{ fields.SetField("Project Name", dt.Rows[0]["Project Name"].ToString()); }
if (de.Key == "Contract No")
{ fields.SetField("Contract No", dt.Rows[0]["Contract Number"].ToString()); }
}
stm.Close();
rdr.Close();
Response.ContentType = "application/pdf";
Response.AddHeader("content-disposition", "attachment; filename=MyFile.pdf");
//To display pdf in the browser window instead of saving, change attachment to inline
Response.BinaryWrite(ms.ToArray());
Response.End();
}
By using MemoryStream along with html headers, you should get a prompt to save the file.

Related

Returning ZipFile in Controller after reading bytes from database

I'm trying to read files from my database (varbinary) and add them to a zip file so that users can download all files related to a specific user.
From what I can gather, I need to read the files from the database, create the zip file, read the files into memory and then write that to the file (doing it without this returned a blank zip file).
It will save the files to the zip, but unfortunately the files are all corrupted.
public FileResult DownloadAllDocuments(int userId)
{
// File name
string ZipFilename = DateTime.Now + "_Files.zip";
// Get files from database
List<DocumentVO> Documents = DocumentDAO.DownloadAllDocuments(userId);
var zipFileMemoryStream = new MemoryStream();
using (ZipArchive archive = new ZipArchive(zipFileMemoryStream, ZipArchiveMode.Update, leaveOpen: true))
{
foreach (DocumentVO document in Documents)
{
var entry = archive.CreateEntry(document.fileName, CompressionLevel.Fastest);
using (var entryStream = entry.Open())
{
entryStream.Write(document.File, 0, document.File.Length);
}
}
}
zipFileMemoryStream.Seek(0, SeekOrigin.Begin);
return File(zipFileMemoryStream, "application/octet-stream", ZipFilename);
}
Please try these codes instead of return File line
using (MemoryStream ms = new MemoryStream())
{
zip.Save(ms);
Response.ClearHeaders();
Response.ClearContent();
Response.Charset = "";
Response.AppendHeader("Content-Disposition", "attachment; filename=" + ZipFilename);
Response.Cache.SetCacheability(HttpCacheability.NoCache);
Response.ContentType = "application/zip";
Response.BinaryWrite(ms.ToArray());
}

C# Response.OutputStream corrupting downloaded file

I am trying to create dynamically created, downloadable ZIP files. The files are created correctly on the server, however when they are sent to the client using "Response.OutputStream" the file becomes corrupted. This only seems to happen when the zip file is over 4GB. Does anyone have any idea why this is?
The exact code I am using is:
string path = #"C:\temp\vid";
Response.BufferOutput = false; // Disable Buffer Output to start the download immediately
// Set custom headers to force browser to download the file instad of trying to open it
Response.ContentType = "application/x-zip-compressed";
Response.AppendHeader("content-disposition", "attachment; filename=Archive.zip");
ZipOutputStream zipOutputStream = new ZipOutputStream(Response.OutputStream, 20000);
zipOutputStream.SetLevel(0); // No compression
zipOutputStream.UseZip64 = UseZip64.On;//Forces Zip64 to be used
zipOutputStream.IsStreamOwner = true;
try
{
foreach (string file in Directory.GetFiles(path, "*.*", SearchOption.AllDirectories))
{
using (var fs = System.IO.File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
ZipEntry entry = new ZipEntry(ZipEntry.CleanName(Path.GetFileName(file))); //Create zip compatible name
zipOutputStream.PutNextEntry(entry); //Adds entry to list
fs.CopyTo(zipOutputStream);
zipOutputStream.CloseEntry();
zipOutputStream.Flush();
Response.Flush();
Response.Clear();
}
}
zipOutputStream.Finish();
zipOutputStream.Close();
Response.End();
Response.Flush();
}
catch
{
Debug.WriteLine("Connection Closed or error");
}
return new HttpStatusCodeResult(HttpStatusCode.OK);

Open a specific page of a pdf file using c sharp

My requirement is as : we have to open a PDF file in new tab. file is opened in new tab successfully, but we want to open 5th page instead-of 1st page. can we achieve it by using c sharp.
My code is below to open pdf in new tab:
MemoryStream stream = new MemoryStream();
stream.Write(fileData, 0, fileData.Length);
HttpContext.Current.Response.Clear();
HttpContext.Current.Response.ContentType = "application/pdf";
string fileName = System.Web.HttpUtility.UrlEncode(yderInfo, System.Text.UTF8Encoding.UTF8).Replace("+", " ");
HttpContext.Current.Response.AppendHeader("Content-Disposition", "inline; attachment;filename*=UTF-8''" + fileName + ".pdf");
HttpContext.Current.Response.OutputStream.Write(stream.GetBuffer(), 0, stream.GetBuffer().Length);
HttpContext.Current.Response.End();
Try using PDF.js(https://mozilla.github.io/pdf.js/) to display your doc in browser and use the below property to set the page.
PDFView.initialBookmark = "page=5";

download multiple pdf

I am trying to download multiple pdf's as attachments in my asp.net application.I have created some templates and filling values using pdfstamper(itextsharp). I am able to fill the values but not able to download.
private void FillForm(string path, DataTable BridgeValues, DataTable Comments, DataTable Maintenance,string Newfilename)
{
try
{
string pdfTemplate = path;
string newFile = Newfilename;
string Pathser = "";
if (!System.IO.Directory.Exists(Server.MapPath(#"~/PDF/")))
{
System.IO.Directory.CreateDirectory(Server.MapPath(#"~/PDF/"));
}
if (Directory.Exists(Server.MapPath(#"~/PDF/")))
{
Pathser = Server.MapPath(#"~/PDF/" + Newfilename);
}
System.IO.MemoryStream mStream = new System.IO.MemoryStream();
// create a new PDF reader based on the PDF template document
PdfReader pdfReader = new PdfReader(pdfTemplate);
PdfStamper pdfStamper = new PdfStamper(pdfReader, new FileStream(Pathser, FileMode.Create));
AcroFields pdfFormFields = pdfStamper.AcroFields;
DataColumn dc = null;
for (int i = 0; i < BridgeValues.Columns.Count - 1; i++)
{
dc = BridgeValues.Columns[i];
pdfFormFields.SetField(dc.ColumnName.ToString(), BridgeValues.Rows[0][dc].ToString());
}
pdfStamper.FormFlattening = true;
// close the pdf
pdfStamper.Close();
////Response.ContentType = "application/octet-stream";
Response.ContentType = "application/pdf";
////Response.AddHeader("Content-Disposition", "attachment; filename=Report.pdf");
Response.AddHeader("Content-Disposition", "attachment; filename=" + Newfilename + "");
////Response.BinaryWrite(mStream.ToArray());
Response.TransmitFile(Server.MapPath(("~/PDF/"+ Newfilename)));
Response.Clear();
Response.End();
}
catch (System.Threading.ThreadAbortException lException)
{
// do nothing
}
}
First time I tried to create one pdf ,it worked but later when I tried to download multiple files it gave an execption.
Unable to evaluate expression because the code is optimized or a native frame is on top of the call stack.
I don't think you can download multiple files by making one request and returning a collection from the action. I would suggest that it you need to allow user to download multiple files you ZIP them and stream the archive down to the browser.
Here is an example of zipping multiple files: http://devpinoy.org/blogs/keithrull/archive/2008/01/25/how-to-create-zip-files-in-c-with-sharpziplib-ziplib.aspx

Trying to open up PDF after creating it with iTextSharp, but can't get it to work?

I have a button when clicked, inserts text into form fields in a pdf and saves the filled pdf to a directory. When I am done editing the pdf, I want to open the pdf in the browswer, but Process.Start() is not working. Is there better way to immediately show the pdf after it has been generated? Here is the code for the button:
protected void btnGenerateQuote_Click(object sender, EventArgs e)
{
string address = txtAddress.Text;
string company = txtCompany.Text;
string outputFilePath = #"C:\Quotes\Quote-" + company + "-.pdf";
PdfReader reader = null;
try
{
reader = new PdfReader(#"C:\Quotes\Quote_Template.pdf");
using (FileStream pdfOutputFile = new FileStream
(outputFilePath, FileMode.Create))
{
PdfStamper formFiller = null;
try
{
formFiller = new PdfStamper(reader, pdfOutputFile);
AcroFields quote_template = formFiller.AcroFields;
//Fill the form
quote_template.SetField("OldAddress", address);
//Flatten - make the text go directly onto the pdf
// and close the form.
//formFiller.FormFlattening = true;
}
finally
{
if (formFiller != null)
{
formFiller.Close();
}
}
}
}
finally
{
reader.Close();
}
//Process.Start(outputFilePath); // does not work
}
Since this is about ASP.NET according to the tags, you should not use Process.Start() but for example code like this:
private void respondWithFile(string filePath, string remoteFileName)
{
if (!File.Exists(filePath))
throw new FileNotFoundException(
string.Format("Final PDF file '{0}' was not found on disk.",
filePath));
var fi = new FileInfo(filePath);
Response.Clear();
Response.AddHeader("Content-Disposition",
String.Format("attachment; filename=\"{0}\"",
remoteFileName));
Response.AddHeader("Content-Length", fi.Length.ToString());
Response.ContentType = "application/octet-stream";
Response.WriteFile(fi.FullName);
Response.End();
}
And this would make the browser give the save/open dialog.

Categories

Resources