mirror of
https://github.com/wmjordan/PDFPatcher.git
synced 2026-10-18 21:52:34 +08:00
1021 lines
40 KiB
C#
1021 lines
40 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Windows.Forms;
|
|
using System.Xml;
|
|
using iTextSharp.text;
|
|
using iTextSharp.text.pdf;
|
|
using MuPdfSharp;
|
|
using PDFPatcher.Common;
|
|
using PDFPatcher.Model;
|
|
using Ext = PDFPatcher.Constants.FileExtensions;
|
|
|
|
namespace PDFPatcher.Processor
|
|
{
|
|
internal static class Worker
|
|
{
|
|
const string OperationCanceled = "已经取消操作。";
|
|
|
|
private static PdfReader OpenPdf(string sourceFile, bool loadPartial, bool removeUnusedObjects) {
|
|
try {
|
|
Tracker.TraceMessage(Tracker.Category.ImportantMessage, String.Concat("打开 PDF 文件:<<", sourceFile, ">>。"));
|
|
return PdfHelper.OpenPdfFile(sourceFile, loadPartial, removeUnusedObjects);
|
|
}
|
|
catch (FileNotFoundException) {
|
|
FormHelper.ErrorBox(String.Concat("找不到文件:“", sourceFile, "”。"));
|
|
return null;
|
|
}
|
|
catch (iTextSharp.text.exceptions.BadPasswordException) {
|
|
Tracker.TraceMessage(Tracker.Category.Error, Messages.PasswordInvalid);
|
|
FormHelper.ErrorBox(Messages.PasswordInvalid);
|
|
return null;
|
|
}
|
|
catch (Exception ex) {
|
|
FormHelper.ErrorBox("在打开 PDF 文件时遇到错误:\n" + ex.Message);
|
|
#if DEBUG
|
|
Tracker.TraceMessage(ex);
|
|
#endif
|
|
return null;
|
|
}
|
|
}
|
|
|
|
internal static void ExtractImages(string sourceFile, ImageExtracterOptions options) {
|
|
const int loadDocProgressWeight = 10;
|
|
Tracker.TraceMessage(Tracker.Category.InputFile, sourceFile);
|
|
var pdf = OpenPdf(sourceFile, true, false); // 由于导出图片一般不需要往复访问文档,可用此选项降低内存占用及提高打开速度
|
|
if (pdf == null) {
|
|
return;
|
|
}
|
|
|
|
var targetPath = options.OutputPath;
|
|
var ranges = PageRangeCollection.Parse(options.PageRange, 1, pdf.NumberOfPages, true);
|
|
var loadCount = loadDocProgressWeight + ranges.TotalPages;
|
|
Tracker.SetProgressGoal(loadCount);
|
|
var op = targetPath;
|
|
var om = options.FileMask;
|
|
try {
|
|
if (Directory.Exists(targetPath) == false) {
|
|
Directory.CreateDirectory(targetPath);
|
|
}
|
|
Tracker.TraceMessage("正在导出图片。");
|
|
Tracker.TrackProgress(loadDocProgressWeight);
|
|
if (FileHelper.HasFileNameMacro(op)) {
|
|
options.OutputPath = ReplaceTargetFileNameMacros(sourceFile, op, pdf);
|
|
}
|
|
if (FileHelper.HasFileNameMacro(om)) {
|
|
options.FileMask = ReplaceTargetFileNameMacros(sourceFile, om, pdf);
|
|
}
|
|
var exp = new ImageExtractor(options, pdf);
|
|
foreach (var range in ranges) {
|
|
foreach (var i in range) {
|
|
exp.ExtractPageImages(pdf, i);
|
|
if (exp.InfoList.Count > 0) {
|
|
Tracker.TraceMessage(Tracker.Category.OutputFile, exp.InfoList[exp.InfoList.Count - 1].FileName);
|
|
}
|
|
Tracker.IncrementProgress(1);
|
|
}
|
|
}
|
|
Tracker.TrackProgress(loadCount);
|
|
Tracker.TraceMessage(Tracker.Category.Alert, "成功提取图片文件,存放目录为:<<" + targetPath + ">>。");
|
|
}
|
|
catch (OperationCanceledException) {
|
|
Tracker.TraceMessage(Tracker.Category.ImportantMessage, OperationCanceled);
|
|
}
|
|
catch (Exception ex) {
|
|
Tracker.TraceMessage(ex);
|
|
FormHelper.ErrorBox("在导出图片时遇到错误:\n" + ex.Message);
|
|
}
|
|
finally {
|
|
options.OutputPath = op;
|
|
options.FileMask = om;
|
|
pdf?.Close();
|
|
}
|
|
}
|
|
|
|
internal static void RenderPages(string sourceFile, ImageRendererOptions options) {
|
|
const int loadDocProgressWeight = 10;
|
|
Tracker.TraceMessage(Tracker.Category.InputFile, sourceFile);
|
|
options.TintColor = System.Drawing.Color.Transparent;
|
|
if (Directory.Exists(options.ExtractImagePath) == false) {
|
|
Directory.CreateDirectory(options.ExtractImagePath);
|
|
}
|
|
MuDocument mupdf = null;
|
|
try {
|
|
mupdf = PdfHelper.OpenMuDocument(sourceFile);
|
|
var ranges = PageRangeCollection.Parse(options.ExtractPageRange, 1, mupdf.PageCount, true);
|
|
int loadCount = loadDocProgressWeight + ranges.TotalPages;
|
|
Tracker.SetProgressGoal(loadCount);
|
|
Tracker.TraceMessage("正在转换图片。");
|
|
Tracker.TrackProgress(loadDocProgressWeight);
|
|
foreach (var range in ranges) {
|
|
foreach (var i in range) {
|
|
var fn = FileHelper.CombinePath(options.ExtractImagePath, i.ToString(options.FileMask) + options.FileFormatExtension);
|
|
using (var p = mupdf.LoadPage(i))
|
|
using (var bmp = p.RenderBitmapPage(options.ImageWidth, 0, options)) {
|
|
if (bmp == null) {
|
|
Tracker.TraceMessage(Tracker.Category.Error, "页面" + i + "的尺寸为空。");
|
|
}
|
|
else if (options.FileFormat == ImageFormat.Tiff) {
|
|
using (var b = Imaging.BitmapHelper.ToBitonal(bmp)) {
|
|
Imaging.BitmapHelper.SaveAs(b, fn);
|
|
}
|
|
}
|
|
else {
|
|
var uc = Imaging.BitmapHelper.GetPalette(bmp);
|
|
if (uc.Length > 256 && options.Quantize) {
|
|
using (var b = Imaging.WuQuantizer.QuantizeImage(bmp)) {
|
|
Imaging.BitmapHelper.SaveAs(b, fn);
|
|
}
|
|
}
|
|
else if (uc.Length <= 256 && Imaging.BitmapHelper.IsIndexed(bmp) == false) {
|
|
using (var b = Imaging.BitmapHelper.ToIndexImage(bmp, uc)) {
|
|
Imaging.BitmapHelper.SaveAs(b, fn);
|
|
}
|
|
}
|
|
else if (options.FileFormat == ImageFormat.Jpeg) {
|
|
Imaging.JpgHelper.Save(bmp, fn, options.JpegQuality);
|
|
}
|
|
else {
|
|
Imaging.BitmapHelper.SaveAs(bmp, fn);
|
|
}
|
|
}
|
|
}
|
|
Tracker.TraceMessage(Tracker.Category.OutputFile, fn);
|
|
Tracker.IncrementProgress(1);
|
|
}
|
|
}
|
|
Tracker.TrackProgress(loadCount);
|
|
Tracker.TraceMessage(Tracker.Category.Alert, "成功转换图片文件,存放目录为:<<" + options.ExtractImagePath + ">>。");
|
|
}
|
|
catch (OperationCanceledException) {
|
|
Tracker.TraceMessage(Tracker.Category.ImportantMessage, OperationCanceled);
|
|
}
|
|
catch (Exception ex) {
|
|
Tracker.TraceMessage(ex);
|
|
FormHelper.ErrorBox("在转换图片时遇到错误:\n" + ex.Message);
|
|
}
|
|
finally {
|
|
mupdf?.Dispose();
|
|
}
|
|
}
|
|
|
|
internal static void RenderPagesToPdf(string sourceFile, ImageRendererOptions options, Document doc) {
|
|
const int loadDocProgressWeight = 10;
|
|
Tracker.TraceMessage(Tracker.Category.InputFile, sourceFile);
|
|
Tracker.TraceMessage(Tracker.Category.OutputFile, options.ExtractImagePath);
|
|
options.TintColor = System.Drawing.Color.Transparent;
|
|
((FilePath)options.ExtractImagePath).CreateContainingDirectory();
|
|
MuDocument mupdf = null;
|
|
try {
|
|
mupdf = PdfHelper.OpenMuDocument(sourceFile);
|
|
var ranges = PageRangeCollection.Parse(options.ExtractPageRange, 1, mupdf.PageCount, true);
|
|
int loadCount = loadDocProgressWeight + ranges.TotalPages;
|
|
Tracker.SetProgressGoal(loadCount);
|
|
Tracker.TraceMessage("正在转换图片。");
|
|
Tracker.TrackProgress(loadDocProgressWeight);
|
|
MemoryStream ms = new MemoryStream();
|
|
var fn = options.FileFormatExtension;
|
|
foreach (var range in ranges) {
|
|
foreach (var i in range) {
|
|
ms.Position = 0;
|
|
using (var p = mupdf.LoadPage(i))
|
|
using (var bmp = p.RenderBitmapPage(options.ImageWidth, 0, options)) {
|
|
if (bmp == null) {
|
|
Tracker.TraceMessage(Tracker.Category.Error, "页面" + i + "的尺寸为空。");
|
|
}
|
|
else if (options.FileFormat == ImageFormat.Tiff) {
|
|
using (var b = Imaging.BitmapHelper.ToBitonal(bmp)) {
|
|
Imaging.BitmapHelper.SaveAs(b, fn, ms);
|
|
}
|
|
}
|
|
else {
|
|
var uc = Imaging.BitmapHelper.GetPalette(bmp);
|
|
if (uc.Length > 256 && options.Quantize) {
|
|
using (var b = Imaging.WuQuantizer.QuantizeImage(bmp)) {
|
|
Imaging.BitmapHelper.SaveAs(b, fn, ms);
|
|
}
|
|
}
|
|
else if (uc.Length <= 256 && Imaging.BitmapHelper.IsIndexed(bmp) == false) {
|
|
using (var b = Imaging.BitmapHelper.ToIndexImage(bmp, uc)) {
|
|
Imaging.BitmapHelper.SaveAs(b, fn, ms);
|
|
}
|
|
}
|
|
else if (options.FileFormat == ImageFormat.Jpeg) {
|
|
Imaging.JpgHelper.Save(bmp, ms, options.JpegQuality);
|
|
}
|
|
else {
|
|
Imaging.BitmapHelper.SaveAs(bmp, fn, ms);
|
|
}
|
|
}
|
|
|
|
doc.SetPageSize((options.Rotation % 180) == 0
|
|
? new iTextSharp.text.Rectangle(p.Bound.Width, p.Bound.Height)
|
|
: new iTextSharp.text.Rectangle(p.Bound.Height, p.Bound.Width));
|
|
doc.NewPage();
|
|
}
|
|
var image = Image.GetInstance(ms.ToArray(), true);
|
|
image.ScalePercent(72f / image.DpiX.SubstituteDefault(72) * 100f, 72f / image.DpiY.SubstituteDefault(72) * 100f);
|
|
doc.Add(image);
|
|
Tracker.IncrementProgress(1);
|
|
}
|
|
}
|
|
Tracker.TrackProgress(loadCount);
|
|
Tracker.TraceMessage(Tracker.Category.Alert, "成功转换图片文件,存放位置为:<<" + options.ExtractImagePath + ">>。");
|
|
}
|
|
catch (OperationCanceledException) {
|
|
Tracker.TraceMessage(Tracker.Category.ImportantMessage, OperationCanceled);
|
|
}
|
|
catch (Exception ex) {
|
|
Tracker.TraceMessage(ex);
|
|
FormHelper.ErrorBox("在转换图片时遇到错误:\n" + ex.Message);
|
|
}
|
|
finally {
|
|
mupdf?.Dispose();
|
|
}
|
|
}
|
|
|
|
internal static void ExportInfo(FilePath sourceFile, FilePath targetFile) {
|
|
Tracker.TraceMessage(Tracker.Category.InputFile, sourceFile);
|
|
Tracker.TraceMessage(Tracker.Category.OutputFile, targetFile);
|
|
var r = OpenPdf(sourceFile, AppContext.LoadPartialPdfFile, false);
|
|
if (r == null) {
|
|
return;
|
|
}
|
|
if (targetFile.IsValidPath == false || targetFile.FileName.Length == 0) {
|
|
Tracker.TraceMessage(Tracker.Category.Error, Messages.InfoFileNameInvalid);
|
|
FormHelper.ErrorBox(Messages.InfoFileNameInvalid);
|
|
return;
|
|
}
|
|
targetFile = FileHelper.MakePathRootedAndWithExtension(targetFile, sourceFile, Ext.Xml, false);
|
|
targetFile.CreateContainingDirectory();
|
|
var export = new DocInfoExporter(r, AppContext.Exporter);
|
|
if (AppContext.Exporter.ExtractImages) {
|
|
AppContext.Exporter.Images.OutputPath = FileHelper.CombinePath(targetFile.Directory, targetFile.FileNameWithoutExtension + "图片文件\\");
|
|
}
|
|
|
|
try {
|
|
Tracker.TraceMessage("正在导出信息文件。");
|
|
if (targetFile.HasExtension(Ext.Txt)) {
|
|
Tracker.SetProgressGoal(50);
|
|
using (TextWriter w = new StreamWriter(targetFile, false, AppContext.Exporter.GetEncoding())) {
|
|
DocInfoExporter.WriteDocumentInfoAttributes(w, sourceFile, r.NumberOfPages);
|
|
export.ExportDocument(w);
|
|
w.WriteLine();
|
|
Tracker.SetProgressGoal(10);
|
|
r.ConsolidateNamedDestinations();
|
|
export.ExportBookmarks(OutlineManager.GetBookmark(r, new UnitConverter()), w, 0, false);
|
|
}
|
|
}
|
|
else {
|
|
var workload = export.EstimateWorkload();
|
|
Tracker.SetProgressGoal(workload);
|
|
using (XmlWriter w = XmlWriter.Create(targetFile, DocInfoExporter.GetWriterSettings())) {
|
|
w.WriteStartDocument();
|
|
w.WriteStartElement(Constants.PdfInfo);
|
|
DocInfoExporter.WriteDocumentInfoAttributes(w, sourceFile, r.NumberOfPages);
|
|
export.ExportDocument(w);
|
|
w.WriteEndElement();
|
|
}
|
|
}
|
|
Tracker.TraceMessage(Tracker.Category.Alert, "成功导出信息文件到 <<" + targetFile + ">>。");
|
|
//if (this._BookmarkBox.Text.Length == 0) {
|
|
// this._BookmarkBox.Text = targetFile;
|
|
//}
|
|
//if (Common.Form.YesNoBox ("已完成导出信息文件到 " + targetFile + ",是否使用内置的编辑器编辑文件?") == DialogResult.Yes) {
|
|
// ShowInfoFileEditorForm (targetFile);
|
|
//}
|
|
}
|
|
catch (OperationCanceledException) {
|
|
Tracker.TraceMessage(Tracker.Category.ImportantMessage, OperationCanceled);
|
|
}
|
|
catch (System.Text.EncoderFallbackException ex) {
|
|
Tracker.TraceMessage(ex);
|
|
FormHelper.ErrorBox("在导出信息文件时遇到错误:\n" + ex.Message + "\n\n请选择在导出信息选项中选择其它编码方式。");
|
|
}
|
|
catch (Exception ex) {
|
|
Tracker.TraceMessage(ex);
|
|
FormHelper.ErrorBox("在导出信息文件时遇到错误:\n" + ex.Message);
|
|
}
|
|
finally {
|
|
r?.Close();
|
|
}
|
|
}
|
|
|
|
internal static void ConvertBookmark(string sourceFile, string targetFile) {
|
|
Tracker.TraceMessage(Tracker.Category.InputFile, sourceFile);
|
|
Tracker.TraceMessage(Tracker.Category.OutputFile, targetFile);
|
|
try {
|
|
var infoDoc = new PdfInfoXmlDocument();
|
|
OutlineManager.ImportSimpleBookmarks(sourceFile, infoDoc);
|
|
using (var w = XmlWriter.Create(targetFile, DocInfoExporter.GetWriterSettings())) {
|
|
infoDoc.Save(w);
|
|
}
|
|
Tracker.TraceMessage(Tracker.Category.Alert, "成功转换信息文件到 <<" + targetFile + ">>。");
|
|
}
|
|
catch (OperationCanceledException) {
|
|
Tracker.TraceMessage(Tracker.Category.ImportantMessage, OperationCanceled);
|
|
}
|
|
catch (Exception ex) {
|
|
Tracker.TraceMessage(ex);
|
|
FormHelper.ErrorBox("在转换书签文件时发生错误:\n" + ex.Message);
|
|
}
|
|
}
|
|
|
|
internal static void PatchDocument(SourceItem.Pdf sourceFile, FilePath targetFile, object infoDoc, ImporterOptions options, PatcherOptions pdfSettings) {
|
|
var sourcePath = sourceFile.FilePath.ToString();
|
|
if (sourceFile.FilePath.IsEmpty) {
|
|
Tracker.TraceMessage(Tracker.Category.Error, "输入文件名为空。");
|
|
return;
|
|
}
|
|
if (String.IsNullOrEmpty(targetFile) || targetFile.IsEmpty) {
|
|
Tracker.TraceMessage(Tracker.Category.Error, "输出文件名为空。");
|
|
return;
|
|
}
|
|
Tracker.TraceMessage(Tracker.Category.InputFile, sourcePath);
|
|
Tracker.TraceMessage(Tracker.Category.OutputFile, targetFile);
|
|
bool overwriteSource = false;
|
|
var pdf = OpenPdf(sourcePath, AppContext.LoadPartialPdfFile, true);
|
|
if (pdf == null) {
|
|
return;
|
|
}
|
|
try {
|
|
DocInfoImporter import;
|
|
var xInfoDoc = infoDoc as PdfInfoXmlDocument;
|
|
var docPath = infoDoc as string;
|
|
if (xInfoDoc != null) {
|
|
import = new DocInfoImporter(options, pdf, pdfSettings, xInfoDoc);
|
|
}
|
|
else if (String.IsNullOrEmpty(docPath)) {
|
|
Tracker.TraceMessage("没有指定信息文件,将按程序界面的设置执行补丁。");
|
|
import = new DocInfoImporter(options, pdf, pdfSettings, null);
|
|
Tracker.TraceMessage("加载源 PDF 文件信息完毕,准备执行补丁操作。");
|
|
}
|
|
else {
|
|
Tracker.TraceMessage(Tracker.Category.ImportantMessage, String.Concat("加载信息文件:<<", docPath, ">>。"));
|
|
import = new DocInfoImporter(options, docPath);
|
|
if (import.InfoDoc != null && VerifyInfoDocument(import.InfoDoc) == false)
|
|
return;
|
|
}
|
|
var pdfEngine = new PdfProcessingEngine(pdf);
|
|
pdfEngine.CreateProcessors(pdfSettings);
|
|
int workload = 110;
|
|
workload += pdfEngine.EstimateWorkload();
|
|
Tracker.SetProgressGoal(workload);
|
|
Tracker.TrackProgress(10);
|
|
|
|
if (pdf.ConfirmUnethicalMode() == false) {
|
|
return;
|
|
}
|
|
|
|
Tracker.TraceMessage("导入文档属性。");
|
|
//var pdfInfo = DocInfoExporter.RewriteDocInfoWithEncoding (pdf.Trailer.GetAsDict (PdfName.INFO), AppContext.Encodings.DocInfoEncoding);
|
|
var info = pdfSettings.MetaData.SpecifyMetaData
|
|
? pdfSettings.MetaData
|
|
//: sourceFile.DocInfo;
|
|
// 不再使用书签文件的文件属性
|
|
: import.ImportDocumentInformation()
|
|
?? sourceFile.DocInfo;
|
|
DocInfoImporter.ImportDocumentInformation(info, pdf, sourcePath);
|
|
Tracker.TrackProgress(20);
|
|
|
|
if (FileHelper.HasFileNameMacro(targetFile)) {
|
|
targetFile = ReplaceTargetFileNameMacros(sourcePath, targetFile, pdf);
|
|
}
|
|
targetFile = FileHelper.MakePathRootedAndWithExtension(targetFile, sourcePath, Ext.Pdf, true);
|
|
targetFile = targetFile.Normalize();
|
|
|
|
Tracker.TraceMessage(Tracker.Category.OutputFile, targetFile);
|
|
if (FileHelper.ComparePath(sourcePath, targetFile)) {
|
|
if (FormHelper.YesNoBox("是否覆盖原始 PDF 文件?\n如处理过程出现错误,覆盖操作将导致原始数据无法恢复!") == DialogResult.No) {
|
|
Tracker.TraceMessage(Tracker.Category.Error, Messages.SourceFileEqualsTargetFile);
|
|
return;
|
|
}
|
|
overwriteSource = true;
|
|
targetFile = sourceFile.FilePath.ChangeExtension(Ext.Tmp).ToString();
|
|
}
|
|
else if (FileHelper.CheckOverwrite(targetFile) == false) {
|
|
return;
|
|
}
|
|
|
|
targetFile.CreateContainingDirectory();
|
|
|
|
using (Stream s = new FileStream(targetFile, FileMode.Create)) {
|
|
var st = new PdfStamper(pdf, s);
|
|
pdfEngine.ProcessDocument(st.Writer);
|
|
#region 处理信息文件
|
|
var processors = new List<IInfoDocProcessor>();
|
|
if (pdfSettings.ViewerPreferences.RemoveZoomRate) {
|
|
processors.Add(new RemoveZoomRateProcessor());
|
|
}
|
|
if (pdfEngine.ExtraData.ContainsKey(DocProcessorContext.CoordinateTransition) && pdfSettings.UnifiedPageSettings.ScaleContent) {
|
|
processors.Add(new GotoDestinationProcessor() {
|
|
TransitionMapper = pdfEngine.ExtraData[DocProcessorContext.CoordinateTransition] as CoordinateTranslationSettings[]
|
|
});
|
|
}
|
|
if (pdfSettings.ViewerPreferences.ForceInternalLink) {
|
|
processors.Add(new ForceInternalDestinationProcessor());
|
|
}
|
|
//var cts = new CoordinateTranslationSettings[pdf.NumberOfPages + 1]; // 页面的位置偏移量
|
|
//var sc = false;
|
|
//if (pdfSettings.PageSettings.Count > 0) {
|
|
// Tracker.TraceMessage ("重设页面尺寸。");
|
|
// pdf.ResetReleasePage ();
|
|
// foreach (var item in pdfSettings.PageSettings) {
|
|
// var ranges = PageRangeCollection.Parse (item.PageRanges, 1, pdf.NumberOfPages, true);
|
|
// foreach (var range in ranges) {
|
|
// foreach (var i in range) {
|
|
// var s = PageDimensionProcessor.ResizePage (pdf.GetPageN (i), item.PaperSize, item.HorizontalAlign, item.VerticalAlign, -1, item.ScaleContent);
|
|
// if (item.ScaleContent && s.XScale != 1 && s.YScale != 1) {
|
|
// PageDimensionProcessor.ScaleContent (pdf, i, s);
|
|
// cts[i] = s; // TODO: 需要解决重复指定相同页面的问题
|
|
// sc = true;
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
// pdf.ResetReleasePage ();
|
|
//}
|
|
if (pdfSettings.UnifiedPageSettings.PaperSize.PaperName == PaperSize.AsPageSize) {
|
|
import.ImportPageSettings(pdf);
|
|
}
|
|
//if (sc == false) {
|
|
// cts = null;
|
|
//}
|
|
#endregion
|
|
|
|
if (pdfSettings.FullCompression) {
|
|
st.SetFullCompression();
|
|
}
|
|
//st.Writer.CompressionLevel = ContextData.CreateDocumentOptions.CompressionLevel;
|
|
var labels = DocInfoImporter.ImportPageLabels(pdfSettings.PageLabels) ?? import.ImportPageLabels();
|
|
if (labels != null) {
|
|
st.Writer.PageLabels = labels;
|
|
}
|
|
if (options.ImportPageLinks || pdfSettings.UnifiedPageSettings.PaperSize.PaperName != PaperSize.AsPageSize/* sc*/) {
|
|
import.ImportPageLinks(pdf, st);
|
|
}
|
|
if (import.InfoDoc != null) {
|
|
PdfDocumentCreator.ProcessInfoItem(import.InfoDoc.DocumentElement.SelectSingleNode(Constants.PageLink) as XmlElement, processors);
|
|
PdfDocumentCreator.ProcessInfoItem(import.InfoDoc.DocumentElement.SelectSingleNode(Constants.NamedDestination) as XmlElement, processors);
|
|
}
|
|
XmlElement bookmarks = null;
|
|
if (options.ImportBookmarks && pdfSettings.RemoveBookmarks == false || xInfoDoc != null) {
|
|
Tracker.TraceMessage("导入书签。");
|
|
bookmarks = import.GetBookmarks() ?? OutlineManager.GetBookmark(pdf, new UnitConverter() { Unit = Constants.Units.Point });
|
|
}
|
|
if (bookmarks != null) {
|
|
// 预处理书签
|
|
processors.Add(new CollapseBookmarkProcessor() { BookmarkStatus = pdfSettings.ViewerPreferences.CollapseBookmark });
|
|
PdfDocumentCreator.ProcessInfoItem(bookmarks, processors);
|
|
if (bookmarks.ChildNodes.Count > 0 || xInfoDoc != null) {
|
|
import.ImportNamedDestinations(pdf, st.Writer);
|
|
OutlineManager.KillOutline(pdf);
|
|
var bm = OutlineManager.WriteOutline(st.Writer, bookmarks, pdf.NumberOfPages);
|
|
if (bm != null) {
|
|
pdf.Catalog.Put(PdfName.OUTLINES, bm);
|
|
}
|
|
if (pdf.Catalog.Contains(PdfName.PAGEMODE) == false) {
|
|
pdf.Catalog.Put(PdfName.PAGEMODE, PdfName.USEOUTLINES);
|
|
}
|
|
}
|
|
else if (String.IsNullOrEmpty(docPath) == false) {
|
|
OutlineManager.KillOutline(pdf);
|
|
}
|
|
}
|
|
Tracker.IncrementProgress(10);
|
|
Tracker.TraceMessage("导入文档设置。");
|
|
import.ImportViewerPreferences(pdf);
|
|
DocInfoImporter.OverrideViewerPreferences(pdfSettings.ViewerPreferences, pdf, st.Writer);
|
|
//import.OverrideDocumentSettings (pdf);
|
|
Tracker.IncrementProgress(5);
|
|
Tracker.TraceMessage("清理输出文件。");
|
|
pdf.RemoveUnusedObjects();
|
|
if (pdf.AcroForm == null) {
|
|
pdf.Trailer.Locate<PdfDictionary>(PdfName.ROOT).Remove(PdfName.ACROFORM);
|
|
}
|
|
Tracker.IncrementProgress(10);
|
|
Tracker.TraceMessage("保存文件:" + targetFile);
|
|
st.Close();
|
|
Tracker.TrackProgress(workload);
|
|
}
|
|
}
|
|
catch (OperationCanceledException) {
|
|
Tracker.TraceMessage(Tracker.Category.ImportantMessage, OperationCanceled);
|
|
return;
|
|
}
|
|
catch (Exception ex) {
|
|
Tracker.TraceMessage(ex);
|
|
FormHelper.ErrorBox("在导入信息时发生错误:\n" + ex.Message);
|
|
return;
|
|
}
|
|
finally {
|
|
if (pdf != null) {
|
|
try {
|
|
pdf.Close();
|
|
}
|
|
catch (Exception ex) {
|
|
// ignore exception
|
|
Tracker.TraceMessage(ex);
|
|
}
|
|
}
|
|
}
|
|
if (overwriteSource) {
|
|
try {
|
|
Tracker.TraceMessage("覆盖输入文件。");
|
|
File.Delete(sourcePath);
|
|
File.Move(targetFile, sourcePath);
|
|
targetFile = sourcePath;
|
|
}
|
|
catch (Exception) {
|
|
FormHelper.ErrorBox("无法覆盖输入文件。\n请手工将“" + Ext.Tmp + "”后缀的临时文件更名为输入文件。");
|
|
}
|
|
}
|
|
Tracker.TraceMessage(Tracker.Category.Alert, "成功导入信息到 <<" + targetFile + ">>。");
|
|
}
|
|
|
|
internal static string ReplaceTargetFileNameMacros(string sourceFile, string targetFile, PdfReader pdf) {
|
|
try {
|
|
return ReplaceTargetFileNameMacros(sourceFile, targetFile, pdf.Trailer.GetAsDict(PdfName.INFO), pdf.NumberOfPages);
|
|
}
|
|
catch (IOException) {
|
|
return ReplaceTargetFileNameMacros(sourceFile, targetFile, null as PdfDictionary, 0);
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// 替换目标文件名的替代符。
|
|
/// </summary>
|
|
/// <param name="sourceFile">用于替换的源文件名。</param>
|
|
/// <param name="targetFile">包含替代符的目标文件名。</param>
|
|
/// <param name="info">源文件的元数据属性。</param>
|
|
/// <param name="pageCount">源文件的页数。</param>
|
|
/// <returns>替换目标文件名后的文件名。</returns>
|
|
internal static string ReplaceTargetFileNameMacros(string sourceFile, string targetFile, PdfDictionary info, int pageCount) {
|
|
string p = null; // 文档属性
|
|
if (info != null) {
|
|
if (info.Contains(PdfName.TITLE)) {
|
|
p = FileHelper.GetValidFileName(info.GetAsString(PdfName.TITLE).ToUnicodeString());
|
|
}
|
|
targetFile = targetFile.Replace(Constants.FileNameMacros.TitleProperty, p ?? Path.GetFileNameWithoutExtension(sourceFile));
|
|
p = String.Empty;
|
|
if (info.Contains(PdfName.SUBJECT)) {
|
|
p = FileHelper.GetValidFileName(info.GetAsString(PdfName.SUBJECT).ToUnicodeString());
|
|
}
|
|
targetFile = targetFile.Replace(Constants.FileNameMacros.SubjectProperty, p);
|
|
p = String.Empty;
|
|
if (info.Contains(PdfName.AUTHOR)) {
|
|
p = FileHelper.GetValidFileName(info.GetAsString(PdfName.AUTHOR).ToUnicodeString());
|
|
}
|
|
targetFile = targetFile.Replace(Constants.FileNameMacros.AuthorProperty, p);
|
|
p = String.Empty;
|
|
if (info.Contains(PdfName.KEYWORDS)) {
|
|
p = FileHelper.GetValidFileName(info.GetAsString(PdfName.KEYWORDS).ToUnicodeString());
|
|
}
|
|
targetFile = targetFile.Replace(Constants.FileNameMacros.KeywordsProperty, p);
|
|
}
|
|
return targetFile
|
|
.Replace(Constants.FileNameMacros.FileName, Path.GetFileNameWithoutExtension(sourceFile))
|
|
.Replace(Constants.FileNameMacros.FolderName, Path.GetFileName(Path.GetDirectoryName(sourceFile)))
|
|
.Replace(Constants.FileNameMacros.PathName, FileHelper.CombinePath(sourceFile.Substring(0, sourceFile.LastIndexOf(Path.DirectorySeparatorChar)), String.Empty))
|
|
.Replace(Constants.FileNameMacros.PageCount, pageCount.ToText());
|
|
}
|
|
|
|
private static bool VerifyInfoDocument(XmlDocument infoDoc) {
|
|
var root = infoDoc.DocumentElement;
|
|
switch (root.Name) {
|
|
case Constants.PdfInfo:
|
|
// 使用中文的书签
|
|
var v = root.GetAttribute(Constants.Info.ProductVersion);
|
|
if (v != Constants.InfoDocVersion
|
|
&& FormHelper.YesNoBox(String.Concat("信息文件不是用这个版本的程序生成的,可能会导入不成功,是否继续?\n当前程序的版本是:", Application.ProductVersion, "\n信息文件的导出程序版本是:", v)) == DialogResult.No) {
|
|
return false;
|
|
}
|
|
break;
|
|
default:
|
|
FormHelper.ErrorBox("信息文件格式有误,根元素不是“" + Constants.PdfInfo + "”。");
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
internal static void ExtractPages(ExtractPageOptions options, string sourceFile, string targetFile) {
|
|
Tracker.TraceMessage(Tracker.Category.InputFile, sourceFile);
|
|
Tracker.TraceMessage(Tracker.Category.OutputFile, targetFile);
|
|
var r = OpenPdf(sourceFile, AppContext.LoadPartialPdfFile, false);
|
|
if (r == null) {
|
|
return;
|
|
}
|
|
try {
|
|
if (r.ConfirmUnethicalMode() == false) {
|
|
return;
|
|
}
|
|
PdfPageExtractor.ExtractPages(options, sourceFile, targetFile, r);
|
|
}
|
|
catch (OperationCanceledException) {
|
|
Tracker.TraceMessage(Tracker.Category.ImportantMessage, OperationCanceled);
|
|
}
|
|
catch (Exception ex) {
|
|
Tracker.TraceMessage(ex);
|
|
FormHelper.ErrorBox("在导出页面内容时出错:\n" + ex.Message);
|
|
}
|
|
finally {
|
|
if (r != null) {
|
|
try {
|
|
r.Close();
|
|
}
|
|
catch (Exception ex) {
|
|
// ignore exception
|
|
Tracker.TraceMessage(ex);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
internal static void MergeDocuments(ICollection<SourceItem> sources, FilePath targetFile, string infoFile) {
|
|
targetFile = targetFile.EnsureExtension(Ext.Pdf);
|
|
Tracker.TraceMessage(Tracker.Category.OutputFile, targetFile.ToString());
|
|
var option = AppContext.Merger;
|
|
var impOptions = AppContext.Importer;
|
|
Document doc = null;
|
|
var sink = new DocumentSink(sources, true);
|
|
if (sink.Workload == 0) {
|
|
Tracker.TraceMessage(Tracker.Category.ImportantMessage, "合并文件列表不包含图片或 PDF 文件。");
|
|
return;
|
|
}
|
|
Tracker.SetProgressGoal(10 + sink.Workload);
|
|
Tracker.TrackProgress(1);
|
|
try {
|
|
GeneralInfo info = null;
|
|
PdfPageLabels labels = null;
|
|
BookmarkContainer bookmarks = null;
|
|
if (String.IsNullOrEmpty(infoFile) == false) {
|
|
Tracker.TraceMessage(Tracker.Category.ImportantMessage, String.Concat("加载信息文件:<<", infoFile, ">>。"));
|
|
var import = new DocInfoImporter(impOptions, infoFile);
|
|
info = import.ImportDocumentInformation();
|
|
labels = import.ImportPageLabels();
|
|
bookmarks = import.GetBookmarks();
|
|
}
|
|
if (labels == null && option.PageLabels.Count > 0) {
|
|
labels = DocInfoImporter.ImportPageLabels(option.PageLabels);
|
|
}
|
|
|
|
var f = targetFile.EnsureExtension(Ext.Pdf);
|
|
Tracker.TraceMessage(Tracker.Category.OutputFile, f.ToString());
|
|
Tracker.TraceMessage(Tracker.Category.ImportantMessage, String.Concat("输出到文件:", f, "。"));
|
|
if (f.IsValidPath == false) {
|
|
Tracker.TraceMessage(Tracker.Category.Error, "输出文件路径无效。");
|
|
return;
|
|
}
|
|
f.CreateContainingDirectory();
|
|
using (Stream s = new FileStream(f, FileMode.Create)) {
|
|
var ps = option.PageSettings;
|
|
doc = new Document(
|
|
new iTextSharp.text.Rectangle(ps.PaperSize.Width, ps.PaperSize.Height),
|
|
ps.Margins.Left, ps.Margins.Right, ps.Margins.Top, ps.Margins.Bottom
|
|
);
|
|
PdfCopy w = option.Deduplicate ? new PdfSmartCopy(doc, s) : new PdfCopy(doc, s);
|
|
if (option.FullCompression) {
|
|
w.SetFullCompression();
|
|
}
|
|
//w.CompressionLevel = ContextData.CreateDocumentOptions.CompressionLevel;
|
|
doc.Open();
|
|
doc.AddCreator(Application.ProductName + " " + Application.ProductVersion);
|
|
if (labels != null) {
|
|
w.PageLabels = labels;
|
|
}
|
|
|
|
Tracker.IncrementProgress(10);
|
|
var creator = new PdfDocumentCreator(sink, option, impOptions, doc, w);
|
|
foreach (var item in sources) {
|
|
creator.ProcessFile(item, creator.PdfBookmarks.BookmarkRoot);
|
|
}
|
|
Tracker.TraceMessage("设置文档选项。");
|
|
DocInfoImporter.ImportDocumentInformation(option.MetaData.SpecifyMetaData
|
|
? option.MetaData
|
|
: info, doc);
|
|
DocInfoImporter.OverrideViewerPreferences(option.ViewerPreferences, null, w);
|
|
if ((bookmarks == null || bookmarks.HasChildNodes == false) && creator.PdfBookmarks.DocumentElement.HasChildNodes) {
|
|
bookmarks = creator.PdfBookmarks.BookmarkRoot;
|
|
}
|
|
if (bookmarks != null && bookmarks.HasChildNodes) {
|
|
Tracker.TraceMessage("写入文档书签。");
|
|
OutlineManager.WriteOutline(w, bookmarks, w.GetPageCount());
|
|
w.ViewerPreferences = PdfWriter.PageModeUseOutlines;
|
|
}
|
|
Tracker.TraceMessage("写入文件索引。");
|
|
Tracker.TraceMessage(Tracker.Category.Alert, $"合并了 {creator.InputDocumentCount.ToText()} 个文件共 {w.GetPageCount()} 页到:<<" + targetFile.ToString() + ">>。");
|
|
w.Close();
|
|
}
|
|
}
|
|
catch (OperationCanceledException) {
|
|
Tracker.TraceMessage(Tracker.Category.ImportantMessage, OperationCanceled);
|
|
}
|
|
catch (Exception ex) {
|
|
Tracker.TraceMessage(ex);
|
|
FormHelper.ErrorBox("在生成文档时出错:\n" + ex.Message);
|
|
}
|
|
finally {
|
|
if (doc != null) {
|
|
try {
|
|
doc.Close();
|
|
}
|
|
catch (Exception ex) {
|
|
// ignore exception
|
|
Tracker.TraceMessage(ex);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
internal static void CreateBookmark(string sourceFile, string bookmarkFile, AutoBookmarkOptions options) {
|
|
Tracker.TraceMessage(Tracker.Category.InputFile, sourceFile);
|
|
Tracker.TraceMessage(Tracker.Category.OutputFile, bookmarkFile);
|
|
var r = OpenPdf(sourceFile, AppContext.LoadPartialPdfFile, false);
|
|
if (r == null) {
|
|
return;
|
|
}
|
|
if (FileHelper.IsPathValid(bookmarkFile) == false || Path.GetFileName(bookmarkFile).Length == 0) {
|
|
Tracker.TraceMessage(Tracker.Category.Error, Messages.InfoFileNameInvalid);
|
|
FormHelper.ErrorBox(Messages.InfoFileNameInvalid);
|
|
return;
|
|
}
|
|
bookmarkFile = FileHelper.MakePathRootedAndWithExtension(bookmarkFile, sourceFile, Ext.Xml, false);
|
|
Tracker.TraceMessage(Tracker.Category.OutputFile, bookmarkFile);
|
|
|
|
if (options.CreateBookmarkForFirstPage) {
|
|
options.FirstPageTitle = Path.GetFileNameWithoutExtension(sourceFile);
|
|
}
|
|
var creator = new AutoBookmarkCreator(r, options);
|
|
|
|
try {
|
|
Tracker.TraceMessage("正在分析 PDF 文件。");
|
|
var workload = creator.EstimateWorkload();
|
|
Tracker.SetProgressGoal(workload);
|
|
using (XmlWriter w = XmlWriter.Create(bookmarkFile, DocInfoExporter.GetWriterSettings())) {
|
|
w.WriteStartDocument();
|
|
w.WriteStartElement(Constants.PdfInfo);
|
|
w.WriteAttributeString(Constants.Info.ProductName, Application.ProductName);
|
|
w.WriteAttributeString(Constants.Info.ProductVersion, Constants.InfoDocVersion);
|
|
w.WriteAttributeString(Constants.Info.ExportDate, DateTime.Now.ToString("yyyy年MM月dd日 HH:mm:ss"));
|
|
//w.WriteAttributeString (Constants.Info.DocumentName, Path.GetFileNameWithoutExtension (sourceFile));
|
|
w.WriteAttributeString(Constants.Info.DocumentPath, sourceFile);
|
|
w.WriteAttributeString(Constants.Info.PageNumber, r.NumberOfPages.ToText());
|
|
creator.ExportAutoBookmarks(w, options);
|
|
w.WriteEndElement();
|
|
}
|
|
Tracker.TraceMessage(Tracker.Category.Alert, "成功导出信息文件到 <<" + bookmarkFile + ">>。");
|
|
}
|
|
catch (OperationCanceledException) {
|
|
Tracker.TraceMessage(Tracker.Category.ImportantMessage, OperationCanceled);
|
|
}
|
|
catch (System.Text.EncoderFallbackException ex) {
|
|
Tracker.TraceMessage(ex);
|
|
FormHelper.ErrorBox("在导出信息文件时遇到错误:\n" + ex.Message + "\n\n请选择在导出信息选项中选择其它编码方式。");
|
|
}
|
|
catch (Exception ex) {
|
|
Tracker.TraceMessage(ex);
|
|
FormHelper.ErrorBox("在导出信息文件时遇到错误:\n" + ex.Message);
|
|
}
|
|
finally {
|
|
if (r != null) {
|
|
r.Close();
|
|
}
|
|
}
|
|
}
|
|
|
|
internal static void Ocr(string sourceFile, string bookmarkFile, OcrOptions options) {
|
|
Tracker.TraceMessage(Tracker.Category.InputFile, sourceFile);
|
|
Tracker.TraceMessage(Tracker.Category.OutputFile, bookmarkFile);
|
|
var r = OpenPdf(sourceFile, AppContext.LoadPartialPdfFile, false);
|
|
if (r == null) {
|
|
return;
|
|
}
|
|
bool noOutputFile = false;
|
|
if (String.IsNullOrEmpty(bookmarkFile)) {
|
|
noOutputFile = true;
|
|
}
|
|
else if (FileHelper.IsPathValid(bookmarkFile) == false || Path.GetFileName(bookmarkFile).Length == 0) {
|
|
Tracker.TraceMessage(Tracker.Category.Error, Messages.InfoFileNameInvalid);
|
|
FormHelper.ErrorBox(Messages.InfoFileNameInvalid);
|
|
return;
|
|
}
|
|
try {
|
|
if (FileHelper.CheckOverwrite(bookmarkFile) == false) {
|
|
return;
|
|
}
|
|
}
|
|
catch (OperationCanceledException) {
|
|
return;
|
|
}
|
|
bookmarkFile = FileHelper.MakePathRootedAndWithExtension(bookmarkFile, sourceFile, Ext.Xml, false);
|
|
Tracker.TraceMessage(Tracker.Category.OutputFile, bookmarkFile);
|
|
|
|
OcrProcessor ocr;
|
|
try {
|
|
ocr = new OcrProcessor(r, options);
|
|
}
|
|
catch (FileNotFoundException ex) {
|
|
Tracker.TraceMessage(ex);
|
|
FormHelper.ErrorBox(ex.Message);
|
|
return;
|
|
}
|
|
|
|
try {
|
|
Tracker.TraceMessage("正在分析 PDF 文件。");
|
|
var workload = ocr.EstimateWorkload();
|
|
Tracker.SetProgressGoal(workload);
|
|
if (noOutputFile) {
|
|
ocr.PerformOcr();
|
|
}
|
|
else if (new FilePath(bookmarkFile).HasExtension(Ext.Txt)) {
|
|
Tracker.TraceMessage(Tracker.Category.OutputFile, bookmarkFile);
|
|
Tracker.TraceMessage("输出简易信息文件:" + bookmarkFile);
|
|
using (var w = new StreamWriter(bookmarkFile, false, AppContext.Exporter.GetEncoding())) {
|
|
DocInfoExporter.WriteDocumentInfoAttributes(w, sourceFile, r.NumberOfPages);
|
|
ocr.SetWriter(w);
|
|
ocr.PerformOcr();
|
|
}
|
|
}
|
|
else {
|
|
Tracker.TraceMessage(Tracker.Category.OutputFile, bookmarkFile);
|
|
Tracker.TraceMessage("输出信息文件:" + bookmarkFile);
|
|
using (var w = XmlWriter.Create(bookmarkFile, DocInfoExporter.GetWriterSettings())) {
|
|
w.WriteStartDocument();
|
|
w.WriteStartElement(Constants.PdfInfo);
|
|
DocInfoExporter.WriteDocumentInfoAttributes(w, sourceFile, r.NumberOfPages);
|
|
ocr.SetWriter(w);
|
|
ocr.PerformOcr();
|
|
w.WriteEndElement();
|
|
}
|
|
}
|
|
|
|
if (noOutputFile == false) {
|
|
Tracker.TraceMessage(Tracker.Category.Alert, "已完成导出信息文件到 <<" + bookmarkFile + ">>。");
|
|
}
|
|
else {
|
|
Tracker.TraceMessage(Tracker.Category.Alert, "分析文档完毕。");
|
|
}
|
|
}
|
|
catch (OperationCanceledException) {
|
|
Tracker.TraceMessage(Tracker.Category.ImportantMessage, OperationCanceled);
|
|
}
|
|
catch (System.Text.EncoderFallbackException ex) {
|
|
Tracker.TraceMessage(ex);
|
|
FormHelper.ErrorBox("在导出信息文件时遇到错误:\n" + ex.Message + "\n\n请选择在导出信息选项中选择其它编码方式。");
|
|
}
|
|
catch (Exception ex) {
|
|
Tracker.TraceMessage(ex);
|
|
FormHelper.ErrorBox("在导出信息文件时遇到错误:\n" + ex.Message);
|
|
}
|
|
finally {
|
|
if (r != null) {
|
|
r.Close();
|
|
}
|
|
}
|
|
}
|
|
|
|
internal static string GetExpandedFileName(SourceItem.Pdf item, string template) {
|
|
string t;
|
|
var s = item.FilePath;
|
|
var d = new PdfDictionary();
|
|
DocInfoImporter.UpdateInfoValue(d, PdfName.TITLE, item.DocInfo.Title, s);
|
|
DocInfoImporter.UpdateInfoValue(d, PdfName.AUTHOR, item.DocInfo.Author, s);
|
|
DocInfoImporter.UpdateInfoValue(d, PdfName.SUBJECT, item.DocInfo.Subject, s);
|
|
DocInfoImporter.UpdateInfoValue(d, PdfName.KEYWORDS, item.DocInfo.Keywords, s);
|
|
t = ReplaceTargetFileNameMacros(s.ToString(), template, d, item.PageCount);
|
|
if (FileHelper.IsPathValid(t) == false) {
|
|
return t;
|
|
}
|
|
else if (Path.GetFileName(t).Length > 0) {
|
|
t = new FilePath(t).EnsureExtension(Ext.Pdf).ToString();
|
|
}
|
|
return Path.GetFullPath(t);
|
|
}
|
|
|
|
internal static void RenameFiles(List<SourceItem.Pdf> items, string template, bool keepSourceFile) {
|
|
Tracker.SetTotalProgressGoal(items.Count);
|
|
Tracker.TraceMessage(String.Concat("使用“", template, "”模板重命名。"));
|
|
foreach (var item in items) {
|
|
try {
|
|
var s = item.FilePath.ToFullPath();
|
|
if (s.ExistsFile == false) {
|
|
Tracker.TraceMessage(Tracker.Category.Error, String.Concat("找不到 PDF 文件:", s));
|
|
continue;
|
|
}
|
|
var t = GetExpandedFileName(item, template);
|
|
Tracker.TraceMessage(Tracker.Category.InputFile, s.ToString());
|
|
Tracker.TraceMessage(Tracker.Category.OutputFile, t);
|
|
Tracker.TraceMessage(Tracker.Category.ImportantMessage, String.Concat("重命名 PDF 文件:", s));
|
|
Tracker.TraceMessage(Tracker.Category.ImportantMessage, String.Concat("到目标 PDF 文件:<<", t, ">>。"));
|
|
if (FileHelper.IsPathValid(t) == false) {
|
|
Tracker.TraceMessage(Tracker.Category.Error, String.Concat("输出文件名 ", t, " 无效。"));
|
|
goto Exit;
|
|
}
|
|
if (s.Equals(t)) {
|
|
Tracker.TraceMessage("源文件与目标文件名称相同。不需重命名。");
|
|
goto Exit;
|
|
}
|
|
else if (Path.GetFileName(t).Trim().Length == 0) {
|
|
Tracker.TraceMessage("输出文件名为空,无法重命名。");
|
|
goto Exit;
|
|
}
|
|
else if (File.Exists(t)) {
|
|
switch (FormHelper.YesNoCancelBox("是否覆盖已存在的 PDF 文件:" + t)) {
|
|
case DialogResult.No:
|
|
goto Exit;
|
|
case DialogResult.Cancel:
|
|
throw new OperationCanceledException();
|
|
default:
|
|
File.Delete(t);
|
|
break;
|
|
}
|
|
}
|
|
if (Directory.Exists(Path.GetDirectoryName(t)) == false) {
|
|
Directory.CreateDirectory(Path.GetDirectoryName(t));
|
|
}
|
|
if (keepSourceFile) {
|
|
File.Copy(s.ToString(), t);
|
|
}
|
|
else {
|
|
File.Move(s.ToString(), t);
|
|
}
|
|
}
|
|
catch (OperationCanceledException) {
|
|
Tracker.TraceMessage(Tracker.Category.Alert, "已取消重命名操作。");
|
|
return;
|
|
}
|
|
catch (Exception ex) {
|
|
Tracker.TraceMessage(ex);
|
|
}
|
|
Exit:
|
|
Tracker.IncrementTotalProgress();
|
|
}
|
|
Tracker.TraceMessage("重命名操作已完成。");
|
|
}
|
|
|
|
internal static void ImportOcr(string sourceFile, string infoFile, string targetFile) {
|
|
if (FileHelper.IsPathValid(sourceFile) == false) {
|
|
Tracker.TraceMessage(Tracker.Category.Error, "输入 PDF 文件路径无效。");
|
|
return;
|
|
}
|
|
if (FileHelper.IsPathValid(targetFile) == false) {
|
|
Tracker.TraceMessage(Tracker.Category.Error, "输出 PDF 文件路径无效。");
|
|
return;
|
|
}
|
|
if (FileHelper.IsPathValid(infoFile) == false) {
|
|
Tracker.TraceMessage(Tracker.Category.Error, "信息文件路径无效。");
|
|
return;
|
|
}
|
|
if (FileHelper.HasExtension(infoFile, Ext.Xml) == false) {
|
|
Tracker.TraceMessage(Tracker.Category.Error, "信息文件不是 XML 文件,只有扩展名为 XML 的识别结果文件才能写入 PDF 文档。");
|
|
return;
|
|
}
|
|
Tracker.TraceMessage(Tracker.Category.InputFile, sourceFile);
|
|
Tracker.TraceMessage(Tracker.Category.OutputFile, targetFile);
|
|
if (FileHelper.ComparePath(sourceFile, targetFile)) {
|
|
Tracker.TraceMessage(Tracker.Category.Error, "输入文件和输出文件不能相同。");
|
|
return;
|
|
}
|
|
if (FileHelper.CheckOverwrite(targetFile) == false) {
|
|
return;
|
|
}
|
|
var pdf = OpenPdf(sourceFile, AppContext.LoadPartialPdfFile, false);
|
|
if (pdf == null) {
|
|
return;
|
|
}
|
|
try {
|
|
using (var infoReader = XmlReader.Create(infoFile, new XmlReaderSettings() { IgnoreComments = true, IgnoreProcessingInstructions = true })) {
|
|
infoReader.MoveToContent(); // 移到根元素
|
|
using (var s = new FileStream(targetFile, FileMode.Create)) {
|
|
var st = new PdfStamper(pdf, s);
|
|
var en = new PdfProcessingEngine(pdf);
|
|
en.ExtraData[DocProcessorContext.OcrData] = infoReader;
|
|
en.DocumentProcessors.Add(new ImportOcrResultProcessor());
|
|
Tracker.SetProgressGoal(en.EstimateWorkload());
|
|
en.ProcessDocument(st.Writer);
|
|
st.Close();
|
|
}
|
|
}
|
|
Tracker.TraceMessage(Tracker.Category.ImportantMessage, "成功写入识别结果到文件:<<" + targetFile + ">>。");
|
|
}
|
|
catch (OperationCanceledException) {
|
|
Tracker.TraceMessage(Tracker.Category.ImportantMessage, OperationCanceled);
|
|
}
|
|
catch (Exception ex) {
|
|
Tracker.TraceMessage(ex);
|
|
FormHelper.ErrorBox("在导入信息时发生错误:\n" + ex.Message);
|
|
}
|
|
finally {
|
|
if (pdf != null) {
|
|
try {
|
|
pdf.Close();
|
|
}
|
|
catch (Exception ex) {
|
|
// ignore exception
|
|
Tracker.TraceMessage(ex);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|