[C#] CKEditor 輸出成Word文件(包含圖案上傳)

2013-06-03

專案需求,必須要將CKEditor 的HTML 結果輸出成Word .docx 檔案

就順便筆記一下..

您當然要有些關於CKEditor 的基本知識

教學參考:

http://blog.kkbruce.net/2010/08/aspnet-ckeditor-ckfinder.html#.UawjNUCcNoE

http://www.dotblogs.com.tw/eaglewolf/archive/2012/01/19/66546.aspx

當然我這邊就不贅述,你在下方直接download sample source code 也是可以直接使用..

首先,我們就先將CKEditor 下載或是透過Nuget 取得..
2013-06-03_122427

再來我們修改 /Scripts/ckeditor/config.js

讓圖片上傳能夠正常..

 

/*
Copyright (c) 2003-2012, CKSource - Frederico Knabben. All rights reserved.
For licensing, see LICENSE.html or http://ckeditor.com/license
*/
 
CKEDITOR.editorConfig = function( config )
{
    config.filebrowserImageUploadUrl = "/fileupload.aspx";
};

其中我們讓檔案上傳的處理路徑指到跟執行目錄下 fileupload.aspx
之後我們來撰寫關於 fileupload.aspx 的部分..
fileupload.apsx 關於 .aspx 得部分只需要留下第一行其他都要刪除

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="fileupload.aspx.cs" Inherits="SimpleConvetCKEditorHTMLToOpenXML.fileupload" %>

fileuploas.aspx.cs 的部分:

using System;
using System.IO;
using System.Web;
 
namespace SimpleConvetCKEditorHTMLToOpenXML
{
    public partial class fileupload : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
 
            HttpPostedFile uploads = Context.Request.Files["upload"];
            string ckediotfuncnum = Context.Request["CKEditorFuncNum"];
            var t = Guid.NewGuid().ToString("N");
 
            //如果暫存資料夾不在就建立
            if (!Directory.Exists(AppDomain.CurrentDomain.BaseDirectory + "uploaded\\"))
            {
                Directory.GetCreationTime(AppDomain.CurrentDomain.BaseDirectory + "uploaded\\");
            }
 
            //判斷圖片是否為.png or .jpg 
            //當然這方法並非很好
            //建議作法依然要打打開圖片做檢查會比較安全
            if (Path.GetExtension(uploads.FileName).ToLower() == ".jpg" || Path.GetExtension(uploads.FileName).ToLower() == ".png")
            {
                string url = "/uploaded/" + t + Path.GetExtension(uploads.FileName);
                File.WriteAllBytes(AppDomain.CurrentDomain.BaseDirectory + "uploaded\\" + t + Path.GetExtension(uploads.FileName), StreamToBytes(uploads.InputStream));
                Response.Write("<script>window.parent.CKEDITOR.tools.callFunction(" + ckediotfuncnum + ",\"" + url + "\");</script>");
 
            }
            else
            {
                Response.Write("<script>alert('上傳格式錯誤');</script>");
                Response.Write("<script>window.parent.CKEDITOR.tools.callFunction(" + ckediotfuncnum + ");</script>");
            }
        }
 
        /// <summary>
        /// 將Stream 轉成  Byte[]
        /// </summary>
        /// <param name="stream"></param>
        /// <returns></returns>
        private byte[] StreamToBytes(Stream stream)
        {
            stream.Position = 0;
            var buffer = new byte[stream.Length];
            for (int totalBytesCopied = 0; totalBytesCopied < stream.Length; )
                totalBytesCopied += stream.Read(buffer, totalBytesCopied, Convert.ToInt32(stream.Length) - totalBytesCopied);
            return buffer;
        }
        
 
    }
}

再來我們看一下關於 轉成Word 檔的部分..
首先,你得先去下載必須的library .

Open XML SDK 2.0 for Microsoft Office

2013-06-03_131046

安裝後我電腦是Windows 8 位置會大概在..

2013-06-03_124533

再來去下載一個方便的工具HtmlToOpenXML

2013-06-03_131249 

接下來,就可以開始寫程式…

using System;
using System.IO;
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;
using NotesFor.HtmlToOpenXml;
 
namespace SimpleConvetCKEditorHTMLToOpenXML
{
    public partial class demo : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
 
        }
 
        protected void btnConvertToWord_Click(object sender, EventArgs e)
        {
            var fileName = Guid.NewGuid().ToString("N") + ".docx";
            var filePathName = AppDomain.CurrentDomain.BaseDirectory + "words\\" +fileName;
            var html = CKEditorControl1.Text;
 
            using (MemoryStream generatedDocument = new MemoryStream())
            {
                using (WordprocessingDocument package = WordprocessingDocument.Create(generatedDocument, WordprocessingDocumentType.Document))
                {
                    MainDocumentPart mainPart = package.MainDocumentPart;
                    if (mainPart == null)
                    {
                        mainPart = package.AddMainDocumentPart();
                        new Document(new Body()).Save(mainPart);
                    }
 
                    HtmlConverter converter = new HtmlConverter(mainPart);
                    Body body = mainPart.Document.Body;
                    //如果有插入圖片,這一行很重要
                    converter.BaseImageUrl = new Uri("http://localhost:16777");
                    var paragraphs = converter.Parse(html);
                    for (int i = 0; i < paragraphs.Count; i++)
                    {
                        body.Append(paragraphs[i]);
                    }
 
                    mainPart.Document.Save();
                }
 
                File.WriteAllBytes(filePathName, generatedDocument.ToArray());
                ltlMessage.Text = "已輸出至" + "words\\" + fileName;
            }
 
        }
    }
}

如果,有遇到

"The type 'System.IO.Packaging.Package' is defined in an assembly that is not referenced. You must add a reference to assembly 'WindowsBase, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"

2013-06-03_124653 需要引入一個library . WindowsBase 

2013-06-03_124716

結果:

2013-06-03_125553 

2013-06-03_125624

Source Code 下載  :https://github.com/donma/ConvertCKEditorToWordOpenXML


當麻許的超技八 2014 | Donma Hsu Design.