FormSubmitXml.cs
// 完毕:
using System.Drawing;
using System.IO;
using System.Linq;
using System.Xml;
using System.Text;
using System.Collections.Generic;
using GrapeCity.Documents.Pdf;
using GrapeCity.Documents.Pdf.AcroForms;
using GrapeCity.Documents.Pdf.Actions;
using GrapeCity.Documents.Pdf.Annotations;
using GrapeCity.Documents.Text;
namespace DsPdfWeb.Demos
{
// 注意:此示例从 GcDocs.Pdf v3 开始已过时。请参阅新的FormDataSubmit
// 样本以获得更好的解决方案。
//
// 此示例创建一个可以提交到服务器的 AcroForm PDF。
// 它依赖服务器将提交的数据放入XML中,
// 将该 XML 导入到包含类似表单的 PDF 中,
// 并将包含加载数据的表单发送回客户端。
// 请注意,生成的 PDF 包含已填写的表单字段
// 显示在客户端浏览器的默认 PDF 查看器中。
// 代码与FormSubmit类似。
public class FormSubmitXml
{
public int CreatePDF(Stream stream)
{
var doc = new GcPdfDocument();
var page = doc.NewPage();
var rc = Common.Util.AddNote("填写表单中的字段,然后单击“提交”将其发送回服务器。" +
"", page);
var g = page.Graphics;
var tf = new TextFormat() { Font = StandardFonts.Times, FontSize = 14 };
var ip = new PointF(72, rc.Bottom + 36);
float fldOffset = 72 * 2 + 46;
float fldHeight = tf.FontSize * 1.2f;
float dY = 32;
// 文本域:
g.DrawString("First name:", tf, ip);
var fldFirstName = new TextField() { Name = "FirstName", Value = "John" };
fldFirstName.Widget.Page = page;
fldFirstName.Widget.Rect = new RectangleF(ip.X + fldOffset, ip.Y, 72 * 3, fldHeight);
fldFirstName.Widget.DefaultAppearance.Font = tf.Font;
fldFirstName.Widget.DefaultAppearance.FontSize = tf.FontSize;
doc.AcroForm.Fields.Add(fldFirstName);
ip.Y += dY;
// 文本域:
g.DrawString("Last name:", tf, ip);
var fldLastName = new TextField() { Name = "LastName", Value = "Smith" };
fldLastName.Widget.Page = page;
fldLastName.Widget.Rect = new RectangleF(ip.X + fldOffset, ip.Y, 72 * 3, fldHeight);
fldLastName.Widget.DefaultAppearance.Font = tf.Font;
fldLastName.Widget.DefaultAppearance.FontSize = tf.FontSize;
doc.AcroForm.Fields.Add(fldLastName);
ip.Y += dY;
// 复选框:
g.DrawString("Subscribe to Mailing List:", tf, ip);
var fldCheckbox = new CheckBoxField() { Name = "Subscribe", Checked = true };
fldCheckbox.Widget.Page = page;
fldCheckbox.Widget.Rect = new RectangleF(ip.X + fldOffset, ip.Y, fldHeight, fldHeight);
doc.AcroForm.Fields.Add(fldCheckbox);
ip.Y += dY;
// 多行文本框:
g.DrawString("Additional information:", tf, ip);
var fldAdditionalInfo = new TextField() { Name = "AdditionalInfo", Multiline = true };
fldAdditionalInfo.Widget.Page = page;
fldAdditionalInfo.Widget.Rect = new RectangleF(ip.X + fldOffset, ip.Y, 72 * 3, fldHeight * 2);
fldAdditionalInfo.Widget.DefaultAppearance.Font = tf.Font;
fldAdditionalInfo.Widget.DefaultAppearance.FontSize = tf.FontSize;
doc.AcroForm.Fields.Add(fldAdditionalInfo);
ip.Y += dY * 2;
// 提交表单按钮:
var btnSubmit = new PushButtonField();
btnSubmit.Widget.Rect = new RectangleF(ip.X + fldOffset, ip.Y, 72, fldHeight);
btnSubmit.Widget.ButtonAppearance.Caption = "Submit";
btnSubmit.Widget.Highlighting = HighlightingMode.Invert;
btnSubmit.Widget.Page = page;
// 提交网址:
btnSubmit.Widget.Activate = new ActionSubmitForm("/Samples/HandleFormSubmitXml");
doc.AcroForm.Fields.Add(btnSubmit);
// 重置表单按钮:
var btnReset = new PushButtonField();
btnReset.Widget.Rect = new RectangleF(ip.X + fldOffset + 72 * 1.5f, ip.Y, 72, fldHeight);
btnReset.Widget.ButtonAppearance.Caption = "Reset";
btnReset.Widget.Highlighting = HighlightingMode.Invert;
btnReset.Widget.Page = page;
btnReset.Widget.Activate = new ActionResetForm();
doc.AcroForm.Fields.Add(btnReset);
ip.Y += dY;
// 完毕:
doc.Save(stream);
return doc.Pages.Count;
}
// 注意:下面的代码由 Web 示例浏览器控制器在表单时使用
// 提交此示例准备的内容,它不是由 CreatePDF() 方法直接调用的。
// 创建一个 GcPdfDocument,将 AcroForm PDF 加载到其中,并用数据填充它
// 使用 GcPdfDocument.ImportFormDataFromXML() 方法。
//
// 当此样本准备表单时,样本控制器将调用此方法
// 由用户提交。样本控制器解析客户端响应并构建
// “values”集合用提交的字段值填充它,然后调用
// 此方法用于准备 XML,将其导入到新创建的 PDF 中,然后返回
// 将生成的 PDF 发送至控制器,控制器将其发送回客户端。
public static Stream ImportFormData(List<FieldExportEntry> values)
{
var pdf = new GcPdfDocument();
using var fs = File.OpenRead(Path.Combine("Resources", "PDFs", "ImportFormXML.pdf"));
pdf.Load(fs);
using (var ms = new MemoryStream())
{
SaveFieldsToXML(values, ms);
ms.Seek(0, SeekOrigin.Begin);
pdf.ImportFormDataFromXML(ms);
}
var outMs = new MemoryStream();
pdf.Save(outMs);
outMs.Seek(0, SeekOrigin.Begin);
return outMs;
}
// 表示要导出到 XML 的表单字段及其值。
public class FieldExportEntry
{
public string Name { get; set; }
public List<string> Values { get; set; }
// Note: this sample does not support child fields:
// public List<FieldTreeNode> Children { get; set; }
}
// 将字段及其值保存到流中。
//
// 该方法与GcPdfDocument.ExportFormDataToXML()类似,具有以下内容
// 重要限制:
// - 它不支持子字段(field.Children集合);
// - 它不处理名称不是有效 XML 名称的字段 (xfdf:original)。
public static void SaveFieldsToXML(List<FieldExportEntry> values, Stream stream)
{
var xws = new XmlWriterSettings()
{
Indent = true,
CloseOutput = false,
Encoding = Encoding.UTF8,
};
using XmlWriter xw = XmlWriter.Create(stream, xws);
xw.WriteStartElement("fields");
xw.WriteAttributeString("xmlns", "xfdf", null, "http://ns.adobe.com/xfdf-transition/");
foreach (var ftn in values)
{
xw.WriteStartElement(ftn.Name);
foreach (var v in ftn.Values)
{
xw.WriteStartElement("value");
// 注意:数组中的值由客户端 PDF 查看器形成,
// 它将“on”复选框值表示为“true”,而 ImportFormDataFromXML
// 期望“on”值表示为“Yes”(这就是 ExportFormDataToXML
// 作品,类似于 Acrobat)。这是一个快速而肮脏的技巧,仅供
// 由于这个样本:
xw.WriteString(v == "true" ? "Yes" : v);
xw.WriteEndElement();
}
xw.WriteEndElement();
}
xw.WriteEndElement();
}
}
}