f6192b8086
SVN-Revision: r1211
500 lines
18 KiB
C#
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 + " 页";
|
|
}
|
|
}
|
|
}
|
|
}
|