最近在研究企業文檔管理,這個是基本上所有企業都需要的軟件,當然也是有很多種解決方案。對於企業文檔來說,最基本的需求就是獨立存儲,共享。這種需求只需要建立一個Windows共享文件夾或者架一個Samba服務器即可實現,無法做復雜的權限管理,統計等。另一種方案就是架一個Web應用,比如SharePoint,就可以實現。
既然是WEB應用,進一步的需求是能夠在線查看文檔,根據用戶需求可能不允許下載,不允許打印文檔。這一點微軟的高級解決方案是使用RMS,能夠設置每個用戶的打開權限,是否打印等,要求必須是域內,而且只管理Office文件的權限,對txt,pdf就沒辦法了。另外一個解決方案是在線文檔預覽,用戶在網頁中查看文檔內容,用戶無需拿到原始文檔,如果有權限的話,可以允許用戶下載文檔。這就就是百度文庫,豆丁之類的網站的功能。下面來說說怎么實現。
1.文檔統一轉換為pdf
這里的文檔我們要看是什么格式,不同的格式有不同的轉換方法。
1.1 Office文檔轉換pdf
對於Office文檔(Word,Excel,PowerPoint),那么可以調用Office提供的COM接口,把文檔另存為PDF。這個要求服務器上必須安裝Office,同時要注意權限,不然很容易導致在本地調試時可以轉換為PDF,但是一旦部署到服務器上去就不行。另外還需要注意的是,如果Office轉換pdf時發生異常,可能導致Office的進程駐留在服務器,不斷駐留Office進程會導致服務器資源耗盡。
這是Office文檔轉換為pdf的代碼:
/// 將word文檔轉換成PDF格式
/// </summary>
/// <param name="sourcePath"></param>
/// <param name="targetPath"></param>
/// <returns></returns>
public static bool ConvertWord2Pdf( string sourcePath, string targetPath)
{
bool result;
Word.WdExportFormat exportFormat= Word.WdExportFormat.wdExportFormatPDF;
object paramMissing = Type.Missing;
Word.Application wordApplication = new Word.Application();
Word.Document wordDocument = null;
try
{
object paramSourceDocPath = sourcePath;
string paramExportFilePath = targetPath;
Word.WdExportFormat paramExportFormat = exportFormat;
Word.WdExportOptimizeFor paramExportOptimizeFor =
Word.WdExportOptimizeFor.wdExportOptimizeForPrint;
Word.WdExportRange paramExportRange = Word.WdExportRange.wdExportAllDocument;
int paramStartPage = 0;
int paramEndPage = 0;
Word.WdExportItem paramExportItem = Word.WdExportItem.wdExportDocumentContent;
Word.WdExportCreateBookmarks paramCreateBookmarks =
Word.WdExportCreateBookmarks.wdExportCreateWordBookmarks;
wordDocument = wordApplication.Documents.Open(
ref paramSourceDocPath, ref paramMissing, ref paramMissing,
ref paramMissing, ref paramMissing, ref paramMissing,
ref paramMissing, ref paramMissing, ref paramMissing,
ref paramMissing, ref paramMissing, ref paramMissing,
ref paramMissing, ref paramMissing, ref paramMissing,
ref paramMissing);
if (wordDocument != null)
wordDocument.ExportAsFixedFormat(paramExportFilePath,
paramExportFormat, false,
paramExportOptimizeFor, paramExportRange, paramStartPage,
paramEndPage, paramExportItem, true,
true, paramCreateBookmarks, true,
true, false,
ref paramMissing);
result = true;
}
finally
{
if (wordDocument != null)
{
wordDocument.Close( ref paramMissing, ref paramMissing, ref paramMissing);
wordDocument = null;
}
if (wordApplication != null)
{
wordApplication.Quit( ref paramMissing, ref paramMissing, ref paramMissing);
wordApplication = null;
}
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
GC.WaitForPendingFinalizers();
}
return result;
}
/// <summary>
/// 將excel文檔轉換成PDF格式
/// </summary>
/// <param name="sourcePath"></param>
/// <param name="targetPath"></param>
/// <returns></returns>
public static bool ConvertExcel2Pdf( string sourcePath, string targetPath)
{
bool result;
object missing = Type.Missing;
Excel.XlFixedFormatType targetType= Excel.XlFixedFormatType.xlTypePDF;
Excel.Application application = null;
Excel.Workbook workBook = null;
try
{
application = new Excel.Application();
object target = targetPath;
workBook = application.Workbooks.Open(sourcePath, missing, missing, missing, missing, missing,
missing, missing, missing, missing, missing, missing, missing, missing, missing);
workBook.ExportAsFixedFormat(targetType, target, Excel.XlFixedFormatQuality.xlQualityStandard, true, false, missing, missing, missing, missing);
result = true;
}
catch
{
result = false;
}
finally
{
if (workBook != null)
{
workBook.Close( true, missing, missing);
workBook = null;
}
if (application != null)
{
application.Quit();
application = null;
}
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
GC.WaitForPendingFinalizers();
}
return result;
}
/// <summary>
/// 將ppt文檔轉換成PDF格式
/// </summary>
/// <param name="sourcePath"></param>
/// <param name="targetPath"></param>
/// <returns></returns>
public static bool ConvertPowerPoint2Pdf( string sourcePath, string targetPath)
{
bool result;
PowerPoint.PpSaveAsFileType targetFileType= PowerPoint.PpSaveAsFileType.ppSaveAsPDF;
PowerPoint.Application application = null;
PowerPoint.Presentation persentation = null;
try
{
application = new PowerPoint.Application();
persentation = application.Presentations.Open(sourcePath, MsoTriState.msoTrue, MsoTriState.msoFalse, MsoTriState.msoFalse);
persentation.SaveAs(targetPath, targetFileType, MsoTriState.msoTrue);
result = true;
}
catch
{
result = false;
}
finally
{
if (persentation != null)
{
persentation.Close();
persentation = null;
}
if (application != null)
{
application.Quit();
application = null;
}
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
GC.WaitForPendingFinalizers();
}
return result;
}
1.2 純文本轉換pdf
如果是文本需要轉換為PDF,我們可以使用iTextSharp這個組件,對於純文本,注意的是源文件中沒有設置字體之類的,需要在轉換成PDF時指定字體,否則對於中文可能由於沒有設置字體而轉換不出來。
/// 將Txt轉換為PDF
/// </summary>
/// <param name="sourcePath"></param>
/// <param name="targetPath"></param>
/// <returns></returns>
public static bool ConvertText2Pdf( string sourcePath, string targetPath)
{
var text = FileHelper.ReadTextFile(sourcePath);
Document document = new Document(PageSize.A4);
try
{
// step 2:創建一個writer用於監聽Document以及通過PDF-stream指向一個文件
PdfWriter.GetInstance(document, new FileStream(targetPath, FileMode.Create));
// step 3: 打開document
document.Open();
var f = GetFont();
// step 4: 添加一段話到document中
document.Add( new Paragraph(text, f));
}
catch (Exception ex)
{
return false;
}
finally
{
if (document.IsOpen())
// step 5: 關閉document
document.Close();
}
return true;
}
private static Font GetFont()
{
var fontPath = ( string) ConfigurationManager.AppSettings[ " FontPath "];
if ( string.IsNullOrEmpty(fontPath)) // 沒有指定字體就用楷體
{
var fontName = " 楷體 ";
if (!FontFactory.IsRegistered(fontName))
{
fontPath = Environment.GetFolderPath(Environment.SpecialFolder.Windows) + @" \Fonts\simkai.ttf ";
FontFactory.Register(fontPath);
}
return FontFactory.GetFont(fontName, BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
}
BaseFont bfChinese = BaseFont.CreateFont(fontPath,BaseFont.IDENTITY_H,BaseFont.NOT_EMBEDDED);
Font fontChinese = new Font(bfChinese, 16f, Font.NORMAL);
return fontChinese;
}
1.3 HTML轉換pdf
HTML中包含的元素較多,比較復雜,主要有兩種方法,一種是調用瀏覽器的接口,讓瀏覽器把HTML打印為PDF,另外就是ITextSharp提供了專門的XML/HTML轉換組件:XML Worker,這個已經獨立出來,不包含在ITextSharp中,需要單獨下載。
{
Document document = new Document(PageSize.A4);
try
{
PdfWriter.GetInstance(document, new FileStream(pdfPath, FileMode.Create));
document.Open();
var fontName = " 楷體 ";
if (!FontFactory.IsRegistered(fontName))
{
var fontPath = Environment.GetFolderPath(Environment.SpecialFolder.Windows) + @" \Fonts\simkai.ttf ";
FontFactory.Register(fontPath);
}
var elements = iTextSharp.tool.xml.XMLWorkerHelper.ParseToElementList(text, @" body {
font-size: 16px;
color: #F00;
font-family: 楷體;
} ");
// iTextSharp.text.
foreach ( var element in elements)
{
document.Add(element);
}
}
catch (DocumentException de)
{
Console.Error.WriteLine(de.Message);
}
catch (IOException ioe)
{
Console.Error.WriteLine(ioe.Message);
}
document.Close();
return true;
}
1.4添加水印
以上都是轉換成pdf的功能,在轉換后,我們可以進一步使用ITextSharp對pdf進行加工,比較常見的添加水印功能。其實就是做一個淡淡的背景透明的圖片,然后打開pdf文件,在每一頁中畫上水印圖片即可。
/// 添加水印
/// </summary>
/// <param name="inputPath"> 源PDF文件路徑 </param>
/// <param name="outputPath"> 加水印后的PDF路徑 </param>
/// <param name="watermarkPath"> 水印圖片的路徑 </param>
/// <param name="error"></param>
/// <returns></returns>
public static bool AddWatermark( string inputPath, string outputPath, string watermarkPath, ref string error)
{
try
{
PdfReader pdfReader = new PdfReader(inputPath);
int numberOfPages = pdfReader.NumberOfPages;
FileStream outputStream = new FileStream(outputPath, FileMode.Create);
PdfStamper pdfStamper = new PdfStamper(pdfReader, outputStream);
PdfContentByte waterMarkContent;
iTextSharp.text.Image image = iTextSharp.text.Image.GetInstance(watermarkPath);
image.SetAbsolutePosition( 10, 10);
for ( int i = 1; i <= numberOfPages; i++)
{
waterMarkContent = pdfStamper.GetUnderContent(i);
waterMarkContent.AddImage(image);
}
pdfStamper.Close();
pdfReader.Close();
outputStream.Close();
return true;
}
catch (Exception ex)
{
error = ex.StackTrace;
return false;
}
}
2.在線預覽pdf文檔
前面已經統一轉換為pdf文檔,接下來就是對pdf的在線預覽。這個在以前是不現實的,現在有了HTML5,只要瀏覽器支持HTML5就可以使用pdf.js庫,將服務器上的pdf文件轉換成HTML5代碼展示在瀏覽器上。另外還有一個解決方案是使用Flash,需要把pdf文件進一步轉換為swf文件,然后由Flash播放器來播放這個文檔。可惜Flash已經是一個過時即將淘汰的技術了,像iPad,iPhone就不支持Flash,所以使用HTML5才是更明智的選擇。
pdf.js網站已經提供了庫和示例,瀏覽頁面是http://mozilla.github.io/pdf.js/web/viewer.html,我們要打開我們轉換的文件,只需要在URL中添加參數即可:
/web/viewer.html?file=yourpdf.pdf
我們可以進一步修改viewer.html中的代碼,根據需求去掉下載,打印等按鈕,禁止用戶下載和打印文件。