我的要求很简单 -
添加考试证书的用户名,日期和分数。这将是一个可下载的文件供他们打印。
我的解决方案(迄今为止) -
通过搜索,我找到了一种方法来做到这一点,这是基于此作为一个部分示例 - How to add a PDF form field (or a text) and link in the page bottom of a page of an existing PDF document using iTextSharp?
虽然我的示例并不精确,但它与此类似,因为我将FileStream与PdfWriter和Document一起使用。我通过段落和Chunk对象添加文本。然后我可以将其写入与响应一起发送的Byte数组。
这是我的问题: 我的Web环境受到AspNet(IIS)用户的限制,该用户永远不会在Web服务器上具有写入功能。我尝试用MemoryStream替换FileSystem对象 - 用于创建PdfWriter对象 由于MemoryStream不可调整大小,因此不会将值写入文件并将输出传递给响应。
我将包括我的工作和简化版本 从任何C#asp.net方法调用此函数以及位于d:\ temp中的2个pdf文件。它会将“Joe Jones”放在模板文件中,并将两者合并为一个带有响应的文件。
示例:
private void CreateCertificate()
{
string seekerName = "Joe Jones";
string pdf1 = "d:\\temp\\CertificateTemplateBody.pdf";
string pdf2 = "d:\\temp\\CertificateTemplateBlank.pdf";
float fontSize = 18;
int fontSizeSeekerName = 45;
PdfReader reader = new PdfReader(pdf1);
Rectangle size = reader.GetPageSizeWithRotation(1);
//dynamic/source text
// my attempt to utilize a MemoryStream in place of this have failed - nonResizable array is the issue.
//using (MemoryStream msOutput = new MemoryStream(GetBytesFromFile(pdf2), true))
//{
using (FileStream fs = new FileStream(pdf2, FileMode.Create, FileAccess.Write))
{
using (Document docSource = new Document(size, 300, 100, 200, 200))
{
using (PdfWriter writer = PdfWriter.GetInstance(docSource, fs))
//This again would be utilizing the MemoryStream which does not work.
//using (PdfWriter writer = PdfWriter.GetInstance(docSource, msOutput))
{
docSource.Open();
PdfContentByte cb = writer.DirectContent;
ColumnText ct = new ColumnText(cb);
Chunk myChunk = new Chunk(seekerName, FontFactory.GetFont(FontFactory.TIMES_ROMAN, fontSizeSeekerName, Font.NORMAL));
float widthText = myChunk.GetWidthPoint();
float centerPoint = (size.Width / 2); // half mark of document
float llx = centerPoint - (widthText / 2); // less half of text width
float lly = widthText;
float urx = centerPoint + (widthText / 2); // plus half of text width
float ury = fontSize * 2;
ct.SetSimpleColumn(new Phrase(myChunk),
llx, //1llx
390, //lly
urx, // 530, //ury
ury,//36,
25,
Element.ALIGN_CENTER | Element.ALIGN_TOP);
ct.Go();
docSource.Close();
}
}
}
//using (FileStream fs = new FileStream(pdf3, FileMode.Create, FileAccess.Write, FileShare.None))
using (MemoryStream ms = new MemoryStream())
{
using (Document doc = new Document(size))
{
using (PdfWriter writer = PdfWriter.GetInstance(doc, ms))
{
doc.Open();
//Get page 1 of the both files then - Add the first file to coordinates 0,0
PdfImportedPage imp1 = writer.GetImportedPage(new PdfReader(pdf1), 1);
PdfImportedPage imp2 = writer.GetImportedPage(new PdfReader(pdf2), 1);
writer.DirectContent.AddTemplate(imp1, 0, 0);
//Since we don't call NewPage the next call will operate on the same page
writer.DirectContent.AddTemplate(imp2, 0, 0);
doc.Close();
}
}
// - test to attach to response.
Response.ClearContent();
Response.ClearHeaders();
Response.ContentType = "application/pdf";
Response.AddHeader("Content-Disposition", "attachment; filename=" + DateTime.Now);
Response.BinaryWrite(ms.ToArray());
Response.End();
Response.Flush();
Response.Clear();
}
}
迄今为止的假设:
在我看来,在这个库中,没有使用fileSystem就无法创建/修改文档,而fileSystem需要Write访问权限。理想情况下,我希望在服务器上有一个模板文件,创建一个添加了用户信息的文档,并与模板文件组合(通过读访问权限打开)。
我没有能力将这一功能配置为具有可写入的网络用户进程的附加应用程序池。 - 这是我的困境/困境。
感谢您阅读本文。 马克
答案 0 :(得分:1)
正如@mkl所说,不要将MemoryStream
绑定到任何东西。当您完成MemoryStream
后,可以将其“导出”为字节数组。 PdfReader
的构造函数有很多重载,其中一个需要一个字节数组,所以你可以将这些字节传递给PdfReader
,就像你创建了一个文件一样。
我不会在下面复制您的整个代码,但这应该会对您有所帮助。
对于第一个区块:
//Create a byte array to use later
Byte[] bytes;
//using (FileStream fs = new FileStream(pdf2, FileMode.Create, FileAccess.Write))
using (MemoryStream msOutput = new MemoryStream())
{
//..PDF work here
//Before closing the stream grab the bytes
bytes = msOutput.ToArray();
}
第二块:
PdfImportedPage imp2 = writer.GetImportedPage(new PdfReader(bytes), 1);