In my controller I want to create a pdf, save it and know only if there are errors, I don't want to get the file to download
public ActionResult CreatePdf(string IDUser, int IDCourse)
{
try
{
string path = Server.MapPath("~/Public/Pdf/");
var fileName = Guid.NewGuid().ToString();
Document pdfDoc = new Document(PageSize.A4, 25, 25, 25, 15);
pdfDoc.SetPageSize(PageSize.A4.Rotate());
var pdfWriter = PdfWriter.GetInstance(pdfDoc, Response.OutputStream);
var fileStream = new FileStream(Path.Combine(path, fileName), FileMode.Create);
pdfWriter = PdfWriter.GetInstance(pdfDoc, fileStream);
pdfDoc.Open();
...
pdfWriter.CloseStream = false;
pdfDoc.Close();
pdfWriter.Close();
fileStream.Close();
db.SaveChanges();
//Response.Buffer = true;
//Response.ContentType = "application/pdf";
//Response.AddHeader("content-disposition", "attachment;filename=\"" + fileName + "\"");
//Response.Cache.SetCacheability(HttpCacheability.NoCache);
//Response.Write(pdfDoc);
//Response.End();
//return File(Response.OutputStream, "application/pdf", fileName.ToString()); // if I want download
return Content("ok");
catch (Exception ex)
{
return Content("error");
}
}
At the beginning I did download the pdf, now I call this procedure in a loop to create more pdfs, so I just want to know if there are errors in the creation.
From the view I call in ajax (jquery) this controller
public ActionResult Create(string listIDUser, int IDCourse)
{
string msg = string.Empty;
try
{
var IDUser = listIDUser.Split(',');
foreach (var item in IDUser)
{
var pdf= CreatePdf(item, IDCourse);
if (pdf!= null)
{
...
}
else
{
return new JsonResult() { Data = new { result = "err", msg = "..." + item } };
}
}
return new JsonResult() { Data = new { result = "ok", msg = "Perfect!" } };
}
catch (Exception ex)
{
return new JsonResult() { Data = new { result = "err", msg = ex.Message } };
}
}
that makes cycles and calls the CreatePdf controller but in the browser with firebug the pdf file returns and not an answer in json as I expect!
Thanks
Related
I have an ASP.net web form application and I have a page that would download a PDF-A3 file created from an HTML string, when I run the appliaction on debug from my device it works perfectly but when I publish the app and put it on the IIS on the server it always throws an error which says:
Message: The document has no pages.
Stack_Trace: at iTextSharp.text.pdf.PdfPages.WritePageTree() at iTextSharp.text.pdf.PdfWriter.Close() at iTextSharp.text.pdf.PdfAWriter.Close() at iTextSharp.text.Document.Close() at Common.PDFHelper.GeneratePDF(String html, String fileName, Boolean isNormalPDF, String detailsJSON) in C:\Libraries\Common\PDFHelper.cs:line 135
I tried at the same time to download a normal PDF and it works fine, but as I said the PDF-A type only works on debug but on release publish build it throws an error.
here is my code:
using iTextSharp.text;
using iTextSharp.text.pdf;
using iTextSharp.tool.xml;
using System;
using System.IO;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Web;
namespace Common
{
public class PDFHelper
{
public void GeneratePDF(string html, string fileName = "", bool isNormalPDF = false, string detailsJSON = "")
{
try
{
if (string.IsNullOrWhiteSpace(fileName))
fileName = Helpers.GenerateRandomString(8);
fileName += Guid.NewGuid().ToString();
int imageIndex = html.IndexOf("data:image/jpeg;base64");
string imageURL = "";
if (imageIndex > -1)
{
try
{
int imageSourceEndIndex = html.IndexOf("\"", imageIndex);
string imageBase64 = html.Substring(imageIndex, imageSourceEndIndex - imageIndex);
imageBase64 = imageBase64.Substring(imageBase64.IndexOf(",") + 1);
byte[] imageBytes = Convert.FromBase64String(imageBase64);
imageURL = HttpContext.Current.Server.MapPath(fileName + ".jpg");
File.WriteAllBytes(imageURL, imageBytes);
html = html.Remove(imageIndex, imageSourceEndIndex - imageIndex);
html = html.Insert(imageIndex, imageURL);
}
catch (Exception ex)
{
MStartLogger.Error(ex, MethodBase.GetCurrentMethod().DeclaringType.Name, MethodBase.GetCurrentMethod().Name, "");
}
}
string xmlFile = "";
byte[] bytes;
using (MemoryStream memoryStream = new MemoryStream())
{
XMLWorkerFontProvider fontProvider = new XMLWorkerFontProvider(Environment.GetFolderPath(Environment.SpecialFolder.Fonts));
if (isNormalPDF)
{
Document pdfDoc = new Document(PageSize.A4);
PdfWriter writer = PdfWriter.GetInstance(pdfDoc, memoryStream);
pdfDoc.Open();
var xmlWorker = XMLWorkerHelper.GetInstance();
MemoryStream htmlContent = new MemoryStream(Encoding.UTF8.GetBytes(html));
xmlWorker.ParseXHtml(writer, pdfDoc, htmlContent, null, Encoding.UTF8, fontProvider);
pdfDoc.Close();
}
else
{
Document pdfDoc = new Document(PageSize.A4);
PdfAWriter writer = PdfAWriter.GetInstance(pdfDoc, memoryStream, PdfAConformanceLevel.PDF_A_3A);
pdfDoc.Open();
writer.CreateXmpMetadata();
string sRGBCSprofile = HttpContext.Current.Server.MapPath("~/Resources/Color/sRGB_CS_profile.icm");
FileStream sRGBCSproFileStream = new FileStream(sRGBCSprofile, FileMode.Open, FileAccess.Read);
var sRGBCSproFileByte = new byte[sRGBCSproFileStream.Length];
sRGBCSproFileStream.Read(sRGBCSproFileByte, 0, sRGBCSproFileByte.Length);
ICC_Profile iccProfile = ICC_Profile.GetInstance(sRGBCSproFileByte);
writer.SetOutputIntents("Custom", "", "http://www.color.org", "sRGB IEC61966-2.1", iccProfile);
PdfDictionary markInfo = new PdfDictionary(PdfName.MARKINFO);
markInfo.Put(PdfName.MARKED, new PdfBoolean("true"));
writer.ExtraCatalog.Put(PdfName.MARKINFO, markInfo);
string xmlString = "";
if (!string.IsNullOrWhiteSpace(xmlString))
{
try
{
xmlFile = HttpContext.Current.Server.MapPath(fileName + ".xml");
File.WriteAllText(xmlFile, xmlString, Encoding.ASCII);
}
catch (Exception ex)
{
Error(ex, MethodBase.GetCurrentMethod().DeclaringType.Name, MethodBase.GetCurrentMethod().Name, "");
}
}
if (!string.IsNullOrWhiteSpace(xmlFile))
{
PdfDictionary parameters = new PdfDictionary();
parameters.Put(PdfName.MODDATE, new PdfDate());
PdfFileSpecification fileSpec = PdfFileSpecification.FileEmbedded(writer, xmlFile, "invoice.xml", null, "application/xml", parameters, 0);
fileSpec.Put(new PdfName("AFRelationship"), new PdfName("Data"));
writer.AddFileAttachment("Invoice Xml", fileSpec);
PdfArray array = new PdfArray();
array.Add(fileSpec.Reference);
writer.ExtraCatalog.Put(new PdfName("AF"), array);
}
var xmlWorker = XMLWorkerHelper.GetInstance();
MemoryStream htmlContent = new MemoryStream(Encoding.UTF8.GetBytes(html));
xmlWorker.ParseXHtml(writer, pdfDoc, htmlContent, null, Encoding.UTF8, fontProvider);
pdfDoc.Close();
}
bytes = memoryStream.ToArray();
memoryStream.Close();
}
// Clears all content output from the buffer stream
HttpContext.Current.Response.Clear();
HttpContext.Current.Response.ContentType = "application/pdf";
HttpContext.Current.Response.AddHeader("content-disposition", "attachment;filename=" + fileName + ".pdf");
HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.NoCache);
HttpContext.Current.Response.BinaryWrite(bytes);
// Delete the temp image.
if (!string.IsNullOrWhiteSpace(imageURL))
File.Delete(imageURL);
if (!string.IsNullOrWhiteSpace(xmlFile))
File.Delete(xmlFile);
HttpContext.Current.Response.End();
}
catch (ThreadAbortException)
{
}
catch (Exception ex)
{
Error(ex, MethodBase.GetCurrentMethod().DeclaringType.Name, MethodBase.GetCurrentMethod().Name, "");
}
}
}
}
I have generated a pdf file from html and now I need to save it to a folder in my project.
I am able to get the generated pdf to download locally but when I send it to the file folder it gets corrupted and will not open.
public void CreateHTML(ComplaintIntakeData cd)
{
string formHtml = "<table class=\"MsoNormal\">";
string complaintTypeHtml = PCSUtilities.GetComplaintTypeHTML(cd);
string providerHtml = "";
if (cd.Providers != null && cd.Providers.Count > 0)
{
providerHtml = PCSUtilities.GetProviderHTML(cd);
}
string facilityHtml = PCSUtilities.GetFacilityHTML(cd);
string anonymousHtml = PCSUtilities.GetAnonymousHTML(cd);
string contactHtml = PCSUtilities.GetContactHTML(cd);
string patientHtml = PCSUtilities.GetPatientHTML(cd);
string detailsHtml = PCSUtilities.GetComplaintDetailsHTML(cd);
formHtml = formHtml + complaintTypeHtml + providerHtml + facilityHtml + anonymousHtml + contactHtml + patientHtml + detailsHtml + "</table>";
formHtml = formHtml.Replace("''", "\"");
// Load HTML template for letter and replace template fields with provider data
string htmlContent = File.ReadAllText(Server.MapPath("~/ComplaintIntakeForm.html"));
htmlContent = htmlContent.Replace("<%ComplaintInformation%>", formHtml);
string fileName = "ComplaintIntakeFile_" + cd.ComplaintGuid.ToString() +".pdf";
using (MemoryStream memStream = new MemoryStream())
{
try
{
// Load up a new PDF doc.
iTextSharp.text.Document pdfDoc = new iTextSharp.text.Document(PageSize.LETTER);
PdfWriter writer = PdfWriter.GetInstance(pdfDoc, memStream);
// writer.CompressionLevel = PdfStream.NO_COMPRESSION;
// Make document tagged PDFVERSION_1_7
writer.SetPdfVersion(PdfWriter.PDF_VERSION_1_7);
writer.SetTagged();
// Set document metadata
writer.ViewerPreferences = PdfWriter.DisplayDocTitle;
pdfDoc.AddLanguage("en-US");
pdfDoc.AddTitle("Complaint Intake Form");
writer.CreateXmpMetadata();
pdfDoc.Open();
var tagProcessors = (DefaultTagProcessorFactory)Tags.GetHtmlTagProcessorFactory();
//tagProcessors.RemoveProcessor(HTML.Tag.IMG);
//tagProcessors.AddProcessor(HTML.Tag.IMG, new CustomImageTagProcessor());
var cssFiles = new CssFilesImpl();
cssFiles.Add(XMLWorkerHelper.GetInstance().GetDefaultCSS());
var cssResolver = new StyleAttrCSSResolver(cssFiles);
var charset = Encoding.UTF8;
var context = new HtmlPipelineContext(new CssAppliersImpl(new XMLWorkerFontProvider()));
context.SetAcceptUnknown(true).AutoBookmark(true).SetTagFactory(tagProcessors);
var htmlPipeline = new HtmlPipeline(context, new PdfWriterPipeline(pdfDoc, writer));
var cssPipeline = new CssResolverPipeline(cssResolver, htmlPipeline);
var worker = new XMLWorker(cssPipeline, true);
var xmlParser = new XMLParser(true, worker, charset);
try
{
using (var sr = new StringReader(htmlContent))
{
xmlParser.Parse(sr);
// xmlParser.Flush();
}
}
catch (Exception e)
{
Response.Write(e.Message);
}
pdfDoc.Close();
//writer.Close();
///this creates a pdf download.
Response.ContentType = "application/pdf";
Response.AddHeader("content-disposition", "attachment; filename=" + fileName);
Response.OutputStream.Write(memStream.GetBuffer(), 0, memStream.GetBuffer().Length);
}
catch (Exception ex)
{
System.Windows.Forms.MessageBox.Show("The following error occurred:\n" + ex.ToString());
}
}
}
when I add the following to create the file. The file is created but it is corrupted and cannot open as a pdf
using (FileStream file = new FileStream(Server.MapPath("~/tempFiles/") + fileName, FileMode.CreateNew))
{
byte[] bytes = new byte[memStream.Length];
memStream.Read(bytes, 0, memStream.Length);
file.Write(bytes, 0, bytes.Length);
}
I think this answer is relevant:
Copy MemoryStream to FileStream and save the file?
Your two code snippets use both memStream and memString and without seeing all the code in context, I'm guessing. Assuming memStream is a Stream that contains the contents of your PDF, you can write it to a file like this:
using (FileStream file = new FileStream(Server.MapPath("~/tempFiles/") + fileName, FileMode.CreateNew))
{
memStream.Position = 0;
memStream.CopyTo(file);
}
I wound up moving the new FileStream call into the PdfWriter.GetInstance method in place of the memStream variable. And was able to get rid of the using filestream code all together.
PdfWriter writer = PdfWriter.GetInstance(pdfDoc, new FileStream(Server.MapPath(path)+"/" + fileName, FileMode.CreateNew));
I have uploaded documents (only image format) to mysql database through c#. This entry in the database table will have reference Id for each transaction. Upon clicking on download button, all uploaded images of respective table id should merge into a single pdf file. How can I Achieve this?. Require C# code to download
Below is the sample code which is not working. It returns system.byte[] as response
[HttpPost]
public static byte[] MergeFile()
{
PdfReader.unethicalreading = true;
using (iTextSharp.text.Document doc = new iTextSharp.text.Document())
{
doc.SetPageSize(PageSize.A4);
using (var ms = new MemoryStream())
{
// PdfWriter wri = PdfWriter.GetInstance(doc, ms);
using (PdfCopy pdf = new `enter code here`PdfCopy(doc, ms))
{
doc.Open();
using (MySqlConnection connection = new MySqlConnection(ConfigurationManager.ConnectionStrings[2].ConnectionString))
{
using (MyDBContext context = new MyDBContext(connection, false))
{
try
{
var getDocs = context.Document.Where(p => p.ReferenceId == 1).ToList();
foreach (DAL.Document info in getDocs)
{
try
{
doc.NewPage();
iTextSharp.text.Document imageDocument = null;
PdfWriter imageDocumentWriter = null;
switch (info.Extension.Trim('.').ToLower())
{
case "image/png":
using (imageDocument = new iTextSharp.text.Document())
{
using (var imageMS = new MemoryStream())
{
using (imageDocumentWriter = PdfWriter.GetInstance(imageDocument, imageMS))
{
imageDocument.Open();
if (imageDocument.NewPage())
{
var image = iTextSharp.text.Image.GetInstance(info.Documents);
image.Alignment = Element.ALIGN_CENTER;
image.ScaleToFit(doc.PageSize.Width - 10, doc.PageSize.Height - 10);
if (!imageDocument.Add(image))
{
throw new Exception("Unable to add image to page!");
}
imageDocument.Close();
imageDocumentWriter.Close();
using (PdfReader imageDocumentReader = new PdfReader(imageMS.ToArray()))
{
var page = pdf.GetImportedPage(imageDocumentReader, 1);
pdf.AddPage(page);
imageDocumentReader.Close();
}
}
}
}
}
break;
}
catch (Exception e)
{
e.Data["FileName"]=info.DocumentName;
throw e;
}
}
}
catch (Exception e)
{
var k = e.Message;
}
}
}
}
if (doc.IsOpen()) doc.Close();
return ms.ToArray();
}
}
}
This one is driving me mad.
I'm trying to implement this example, which is working if you download the project, but I have a WebApi2 app, not the classic aspx, so I have problems with Response (The name 'Response' does not exist in the current context).
var document = new Document(PageSize.A4, 50, 50, 25, 25);
var output = new MemoryStream();
var writer = PdfWriter.GetInstance(document, output);
document.Open();
document.Add(new Paragraph("Hello World"));
document.Close();
Response.ContentType = "application/pdf";
Response.AddHeader("Content-Disposition", string.Format("attachment;filename=testDoc.pdf", "some string"));
Response.BinaryWrite(output.ToArray());
I tried several things like adding HttpContext.Current to the Response like this:
HttpContext.Current.Response.ContentType = "application/pdf";
HttpContext.Current.Response.AddHeader("Content-Disposition", string.Format("attachment;filename=testDoc.pdf", "some string"));
HttpContext.Current.Response.BinaryWrite(output.ToArray());
But there's no way I can make the .pdf document to show on/download from the browser.
What am I to do here?
With HttpResponseMessage:
public HttpResponseMessage ExampleOne()
{
var stream = CreatePdf();
return new HttpResponseMessage
{
Content = new StreamContent(stream)
{
Headers =
{
ContentType = new MediaTypeHeaderValue("application/pdf"),
ContentDisposition = new ContentDispositionHeaderValue("attachment")
{
FileName = "myfile.pdf"
}
}
},
StatusCode = HttpStatusCode.OK
};
}
With IHttpActionResult:
public IHttpActionResult ExampleTwo()
{
var stream = CreatePdf();
return ResponseMessage(new HttpResponseMessage
{
Content = new StreamContent(stream)
{
Headers =
{
ContentType = new MediaTypeHeaderValue("application/pdf"),
ContentDisposition = new ContentDispositionHeaderValue("attachment")
{
FileName = "myfile.pdf"
}
}
},
StatusCode = HttpStatusCode.OK
});
}
Here is the CreatePdf method:
private Stream CreatePdf()
{
using (var document = new Document(PageSize.A4, 50, 50, 25, 25))
{
var output = new MemoryStream();
var writer = PdfWriter.GetInstance(document, output);
writer.CloseStream = false;
document.Open();
document.Add(new Paragraph("Hello World"));
document.Close();
output.Seek(0, SeekOrigin.Begin);
return output;
}
}
This question is related to one I asked here on "How can I prompt the user for a save location from a Sharepoint page?"
What I need to do is, after generating a PDF thus:
private void GeneratePDF(List<ListColumns> listOfListItems)
{
. . .
//Create a stream that we can write to, in this case a MemoryStream
StringBuilder sb = new StringBuilder();
using (var ms = new MemoryStream())
{
using (var doc = new Document(PageSize.A4, 25, 25, 10, 10))
{
//Create a writer that's bound to our PDF abstraction and our stream
using (var writer = PdfWriter.GetInstance(doc, ms))
{
//Open the document for writing
doc.Open();
Paragraph docTitle = new Paragraph("UCSC - Direct Payment Form", timesBold16UCSCBlue);
doc.Add(docTitle);
Paragraph subTitle = new Paragraph("(Not to be used for reimbursement of services)", timesRoman9Font);
subTitle.IndentationLeft = 20;
doc.Add(subTitle);
. . . // tons of iTextSharp PDF-generation code elided for brevity
String htmlToRenderAsPDF = sb.ToString();
//XMLWorker also reads from a TextReader and not directly from a string
using (var srHtml = new StringReader(htmlToRenderAsPDF))
{
XMLWorkerHelper.GetInstance().ParseXHtml(writer, doc, srHtml);
}
doc.Close();
}
}
try
{
var bytes = ms.ToArray();
// This is currently saved to a location on the server such as C:\Users\TEMP.SP.005\Desktop\iTextSharpTest.pdf (but the number (such as
"005" irregularly increments))
String pdfFileID = GetYYYYMMDDAndUserNameAndAmount();
String pdfFileName = String.Format("DirectPayDynamic_{0}.pdf", pdfFileID);
String fileFullpath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory), pdfFileName);
String fileLinkBase = "Generated PDF: {1}";
String filelink = String.Format(fileLinkBase, fileFullpath, pdfFileName);
File.WriteAllBytes(fileFullpath, bytes);
var pdflink = new Label
{
CssClass = "finaff-webform-field-label",
Text = filelink
};
this.Controls.Add(pdflink);
}
catch (DocumentException dex)
{
throw (dex);
}
catch (IOException ioex)
{
throw (ioex);
}
catch (Exception ex)
{
throw (ex);
}
}
} // GeneratePDF
...afford the user the opportunity to save that file to their local machine (currently, it is being saved on the server).
IOW, what I basically want to do is replace this line:
String fileFullpath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory), pdfFileName);
...with something like:
String fileFullpath = "Hey, bloke (or blokette), where do you want to save this?"
This is obviously possible, and even somewhat common, as many websites will generate files for you and then allow you to save those
generated files to either a location you select or a default location, such as your downloads folder.
Either a server-side (C#) or a client-side (jQuery) solution is acceptable, although I prefer server-side, as that is where the PDF is being generated.
When I had to force an Excel spreadsheet to download to the client, I used this code, which may point you to where you are wanting to get:
Control xxx of type 'LinkButton' must be placed inside a form tag with runat=server
protected void ExportExcelFile(object Sender, EventArgs e) { //export to excel
var grdResults = new DataGrid(); // REF: https://stackoverflow.com/q/28155089/153923
if (periodCriteria.SelectedValue == "year") {
grdResults = RollupDG;
} else {
grdResults = QuarterDG;
}
var response = HttpContext.Current.Response;
response.Clear();
response.Charset = String.Empty;
response.ContentType = "application/vnd.ms-excel";
response.AddHeader("Content-Disposition", "attachment; filename=GlBudgetReport.xls");
using (var sw = new StringWriter()) {
using (var htw = new HtmlTextWriter(sw)) {
grdResults.RenderControl(htw);
response.Write(sw.ToString());
response.End();
}
}
}