SVN r1211
SVN-Revision: r1211
This commit is contained in:
@@ -0,0 +1,499 @@
|
||||
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 + " 页";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user