Files
lserp_cs_6.0/插件库/Lskj.Control/Model/SignaturePrinting.cs
T
cyf f6192b8086 SVN r1211
SVN-Revision: r1211
2026-06-18 01:43:59 +00:00

500 lines
18 KiB
C#

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Printing;
using System.IO;
using System.Net;
using System.Threading;
using System.Web;
using System.Windows.Forms;
using iTextSharp.text.pdf;
using Lskj.Util;
using O2S.Components.PDFView4NET;
using O2S.Components.PDFView4NET.Printing;
namespace Lskj.Control.Model
{
public class SignaturePrinting
{
private const string DefaultSignatureImageFileName = "signature.png";
private const float DefaultSignatureWidth = 160f;
private const float DefaultSignatureOpacity = 1f;
public static string PreviewByUrl(string pdfUrl)
{
return PreviewByUrls(new string[] { pdfUrl });
}
public static string PreviewByUrls(string pdfUrls)
{
return PreviewByUrls(SplitUrls(pdfUrls));
}
public static string PreviewByUrls(IEnumerable<string> pdfUrls)
{
return PreviewByUrls(pdfUrls, null);
}
public static string PreviewByUrls(IEnumerable<string> pdfUrls, string signatureImagePath)
{
try
{
string previewFile = CreateSignedPreviewFile(pdfUrls, signatureImagePath);
ShowPreviewForm(previewFile);
return previewFile;
}
catch (Exception ex)
{
MessageUtil.Show("签章打印预览失败", ex.Message);
return string.Empty;
}
}
public static string CreateSignedPreviewFile(IEnumerable<string> pdfUrls, string signatureImagePath)
{
List<string> urls = NormalizeUrls(pdfUrls);
if (urls.Count == 0)
{
throw new ArgumentException("未传入需要打印的PDF文件地址。");
}
string signatureImage = ResolveSignatureImagePath(signatureImagePath);
string tempPath = PubUtil.SignatureFilePath;
PubUtil.ClearFilesInDirectory(tempPath);
List<string> signedFiles = new List<string>();
for (int i = 0; i < urls.Count; i++)
{
string downloadedFile = DownloadPdf(urls[i], tempPath, i + 1);
string signedFile = Path.Combine(tempPath, "signed_" + (i + 1).ToString("000") + "_" + Path.GetFileName(downloadedFile));
AddCenteredSignature(downloadedFile, signedFile, signatureImage, DefaultSignatureWidth, DefaultSignatureOpacity);
signedFiles.Add(signedFile);
}
if (signedFiles.Count == 1)
{
return signedFiles[0];
}
string mergedFile = Path.Combine(tempPath, "signature_preview_" + DateTime.Now.ToString("yyyyMMddHHmmssfff") + ".pdf");
MergePdfFiles(signedFiles, mergedFile);
return mergedFile;
}
private static IEnumerable<string> SplitUrls(string pdfUrls)
{
if (string.IsNullOrWhiteSpace(pdfUrls))
{
return new string[0];
}
return pdfUrls.Split(new string[] { "\r\n", "\n", ";", "|" }, StringSplitOptions.RemoveEmptyEntries);
}
private static List<string> NormalizeUrls(IEnumerable<string> pdfUrls)
{
List<string> urls = new List<string>();
if (pdfUrls == null)
{
return urls;
}
foreach (string item in pdfUrls)
{
if (!string.IsNullOrWhiteSpace(item))
{
urls.Add(item.Trim());
}
}
return urls;
}
private static string ResolveSignatureImagePath(string signatureImagePath)
{
string imagePath = signatureImagePath;
if (string.IsNullOrWhiteSpace(imagePath))
{
imagePath = Path.Combine(PubUtil.PdfSignImagePath, DefaultSignatureImageFileName);
}
else if (!Path.IsPathRooted(imagePath))
{
imagePath = Path.Combine(PubUtil.AbsolutelyPath, imagePath);
}
if (File.Exists(imagePath))
{
return imagePath;
}
string[] extensions = new string[] { "*.png", "*.jpg", "*.jpeg", "*.bmp", "*.gif" };
foreach (string extension in extensions)
{
string[] files = Directory.GetFiles(PubUtil.PdfSignImagePath, extension);
if (files.Length > 0)
{
return files[0];
}
}
throw new FileNotFoundException("未找到签章图片,请将签章图片放到:" + imagePath);
}
private static string DownloadPdf(string sourceUrl, string tempPath, int index)
{
string fileName = GetSafePdfFileName(sourceUrl, index);
string localFile = Path.Combine(tempPath, "download_" + index.ToString("000") + "_" + fileName);
if (File.Exists(sourceUrl))
{
File.Copy(sourceUrl, localFile, true);
return localFile;
}
Uri uri;
if (!Uri.TryCreate(sourceUrl, UriKind.Absolute, out uri))
{
throw new ArgumentException("PDF文件地址无效:" + sourceUrl);
}
TryEnableTls12();
using (TimeoutWebClient client = new TimeoutWebClient())
{
client.Headers.Add(HttpRequestHeader.UserAgent, "Mozilla/5.0");
client.DownloadFile(uri, localFile);
}
return localFile;
}
private static string GetSafePdfFileName(string sourceUrl, int index)
{
string fileName = string.Empty;
Uri uri;
if (Uri.TryCreate(sourceUrl, UriKind.Absolute, out uri))
{
fileName = HttpUtility.UrlDecode(Path.GetFileName(uri.LocalPath));
}
else
{
fileName = Path.GetFileName(sourceUrl);
}
if (string.IsNullOrWhiteSpace(fileName))
{
fileName = "file_" + index.ToString("000") + ".pdf";
}
foreach (char invalidChar in Path.GetInvalidFileNameChars())
{
fileName = fileName.Replace(invalidChar, '_');
}
if (!Path.GetExtension(fileName).Equals(".pdf", StringComparison.OrdinalIgnoreCase))
{
fileName = Path.GetFileNameWithoutExtension(fileName) + ".pdf";
}
return fileName;
}
private static void AddCenteredSignature(string inputPdfPath, string outputPdfPath, string signatureImagePath, float signatureWidth, float opacity)
{
using (PdfReader reader = new PdfReader(inputPdfPath))
{
using (FileStream outputStream = new FileStream(outputPdfPath, FileMode.Create, FileAccess.Write, FileShare.None))
{
PdfStamper stamper = null;
try
{
stamper = new PdfStamper(reader, outputStream);
for (int pageIndex = 1; pageIndex <= reader.NumberOfPages; pageIndex++)
{
iTextSharp.text.Rectangle pageSize = reader.GetPageSizeWithRotation(pageIndex);
iTextSharp.text.Image signature = iTextSharp.text.Image.GetInstance(signatureImagePath);
float width = Math.Min(signatureWidth, pageSize.Width * 0.6f);
float height = width * signature.Height / signature.Width;
float left = pageSize.Left + (pageSize.Width - width) / 2f;
float bottom = pageSize.Bottom + (pageSize.Height - height) / 2f;
signature.ScaleAbsolute(width, height);
signature.SetAbsolutePosition(left, bottom);
PdfContentByte content = stamper.GetOverContent(pageIndex);
PdfGState state = new PdfGState();
state.FillOpacity = opacity;
content.SaveState();
content.SetGState(state);
content.AddImage(signature);
content.RestoreState();
}
}
finally
{
if (stamper != null)
{
stamper.Close();
}
}
}
}
}
private static void MergePdfFiles(List<string> pdfFiles, string outputPdfPath)
{
iTextSharp.text.Document document = null;
PdfCopy copy = null;
FileStream outputStream = null;
try
{
outputStream = new FileStream(outputPdfPath, FileMode.Create, FileAccess.Write, FileShare.None);
for (int fileIndex = 0; fileIndex < pdfFiles.Count; fileIndex++)
{
using (PdfReader reader = new PdfReader(pdfFiles[fileIndex]))
{
if (document == null)
{
document = new iTextSharp.text.Document(reader.GetPageSizeWithRotation(1));
copy = new PdfCopy(document, outputStream);
document.Open();
}
for (int pageIndex = 1; pageIndex <= reader.NumberOfPages; pageIndex++)
{
copy.AddPage(copy.GetImportedPage(reader, pageIndex));
}
}
}
}
finally
{
if (document != null)
{
document.Close();
}
else if (outputStream != null)
{
outputStream.Close();
}
}
}
private static void ShowPreviewForm(string pdfFile)
{
if (Thread.CurrentThread.GetApartmentState() != ApartmentState.STA)
{
throw new InvalidOperationException("签章打印预览需要在UI线程调用。");
}
using (SignaturePreviewForm previewForm = new SignaturePreviewForm(pdfFile))
{
Form owner = Form.ActiveForm;
if (owner != null && !owner.IsDisposed)
{
previewForm.ShowDialog(owner);
}
else
{
previewForm.ShowDialog();
}
}
}
private static void TryEnableTls12()
{
try
{
ServicePointManager.SecurityProtocol = ServicePointManager.SecurityProtocol | (SecurityProtocolType)3072;
}
catch
{
}
}
private class TimeoutWebClient : WebClient
{
public int Timeout { get; set; }
public TimeoutWebClient()
{
Timeout = 60000;
}
protected override WebRequest GetWebRequest(Uri address)
{
WebRequest request = base.GetWebRequest(address);
if (request != null)
{
request.Timeout = Timeout;
}
return request;
}
}
private class SignaturePreviewForm : Form
{
private readonly string _pdfFile;
private readonly PDFDocument _document;
private readonly PDFPageView _pageView;
private readonly ToolStripLabel _pageLabel;
public SignaturePreviewForm(string pdfFile)
{
_pdfFile = pdfFile;
_document = new PDFDocument();
_pageView = new PDFPageView();
_pageLabel = new ToolStripLabel();
InitializeComponent();
Load += OnFormLoad;
FormClosed += OnFormClosed;
}
private void InitializeComponent()
{
Text = "签章打印预览";
StartPosition = FormStartPosition.CenterScreen;
Width = 1000;
Height = 760;
ToolStrip toolStrip = new ToolStrip();
toolStrip.GripStyle = ToolStripGripStyle.Hidden;
toolStrip.Dock = DockStyle.Top;
ToolStripButton printButton = new ToolStripButton("打印");
printButton.Click += OnPrintClick;
ToolStripButton firstButton = new ToolStripButton("首页");
firstButton.Click += OnFirstClick;
ToolStripButton prevButton = new ToolStripButton("上一页");
prevButton.Click += OnPrevClick;
ToolStripButton nextButton = new ToolStripButton("下一页");
nextButton.Click += OnNextClick;
ToolStripButton lastButton = new ToolStripButton("末页");
lastButton.Click += OnLastClick;
ToolStripButton zoomOutButton = new ToolStripButton("缩小");
zoomOutButton.Click += OnZoomOutClick;
ToolStripButton zoomInButton = new ToolStripButton("放大");
zoomInButton.Click += OnZoomInClick;
toolStrip.Items.Add(printButton);
toolStrip.Items.Add(new ToolStripSeparator());
toolStrip.Items.Add(firstButton);
toolStrip.Items.Add(prevButton);
toolStrip.Items.Add(nextButton);
toolStrip.Items.Add(lastButton);
toolStrip.Items.Add(new ToolStripSeparator());
toolStrip.Items.Add(zoomOutButton);
toolStrip.Items.Add(zoomInButton);
toolStrip.Items.Add(new ToolStripSeparator());
toolStrip.Items.Add(_pageLabel);
_document.PageLayout = PDFPageLayout.SinglePage;
_document.PageMode = PDFPageMode.UseNone;
_pageView.Dock = DockStyle.Fill;
_pageView.Document = _document;
_pageView.PageDisplayLayout = PDFPageDisplayLayout.OneColumn;
_pageView.ZoomMode = PDFZoomMode.FitWidth;
_pageView.WorkMode = UserInteractiveWorkMode.None;
_pageView.BackColor = Color.White;
Controls.Add(_pageView);
Controls.Add(toolStrip);
}
private void OnFormLoad(object sender, EventArgs e)
{
_document.Load(_pdfFile);
_pageView.PageNumber = 0;
UpdatePageLabel();
}
private void OnFormClosed(object sender, FormClosedEventArgs e)
{
try
{
_document.Close();
}
catch
{
}
}
private void OnPrintClick(object sender, EventArgs e)
{
try
{
using (PrintDialog printDialog = new PrintDialog())
{
printDialog.AllowSomePages = true;
printDialog.UseEXDialog = true;
printDialog.PrinterSettings = new PrinterSettings();
if (printDialog.ShowDialog(this) != DialogResult.OK)
{
return;
}
PDFPrintSettings settings = new PDFPrintSettings(printDialog.PrinterSettings);
settings.DocumentName = Path.GetFileName(_pdfFile);
settings.AutoRotate = true;
settings.PageScaling = PageScaling.FitToPrinterMarginsProportional;
PDFPrintContent content = PDFPrintContent.Page | PDFPrintContent.Annotations | PDFPrintContent.FormFields;
_document.Print(settings, content);
}
}
catch (Exception ex)
{
MessageUtil.Show("签章PDF打印失败", ex.Message);
}
}
private void OnFirstClick(object sender, EventArgs e)
{
_pageView.GoToFirstPage();
UpdatePageLabel();
}
private void OnPrevClick(object sender, EventArgs e)
{
_pageView.GoToPrevPage();
UpdatePageLabel();
}
private void OnNextClick(object sender, EventArgs e)
{
_pageView.GoToNextPage();
UpdatePageLabel();
}
private void OnLastClick(object sender, EventArgs e)
{
_pageView.GoToLastPage();
UpdatePageLabel();
}
private void OnZoomOutClick(object sender, EventArgs e)
{
_pageView.ZoomMode = PDFZoomMode.Custom;
_pageView.Zoom = Math.Max(0.25d, _pageView.Zoom - 0.1d);
}
private void OnZoomInClick(object sender, EventArgs e)
{
_pageView.ZoomMode = PDFZoomMode.Custom;
_pageView.Zoom = Math.Min(5d, _pageView.Zoom + 0.1d);
}
private void UpdatePageLabel()
{
int pageCount = _document.PageCount;
int pageNumber = pageCount == 0 ? 0 : _pageView.PageNumber + 1;
_pageLabel.Text = "第 " + pageNumber + " / " + pageCount + " 页";
}
}
}
}