2013-02-27 54 views
7

我有一個將富文本內容從一個文檔複製到另一個文檔的MIME的解決方案。見http://per.lausten.dk/blog/2012/12/xpages-dynamically-updating-rich-text-content-in-a-ckeditor.html。我在應用程序中使用它作爲用戶將內容模板插入新文檔並使內容在CKEditor中即時顯示的方式。將富文本和圖像從一個文檔複製到另一個文檔的MIME

問題在於複製中不包含內嵌圖像 - 只是對臨時存儲圖像的引用。這意味着圖像僅對當前會話中的當前用戶可見。所以不是很有用。

如何包含圖像?

更新2013年10月4日: 我仍在尋找解決方案。

+1

需要一些MIME魔術。我嘗試爲你做點什麼。 – stwissel 2013-10-07 09:18:25

回答

4

我終於找到了它的工作。它更簡單,甚至沒有涉及MIME。訣竅是修改工作HTML圖像標籤包括base64編碼的圖像,使得SRC標籤可以使用此格式(用GIF作爲例子所示):

src="data:image/gif;base64,<base64 encoded image>" 

我已經有代碼必要從富文本字段中獲取HTML(請參閱我的問題中已提到的my blog post)。所以我需要的是用正確的src格式(包括base64編碼圖像)替換圖像src標籤。

以下代碼獲取HTML和通過每個包括圖像的前進,並修改SRC標記:

String html = this.document.getValue(fieldName).toString(); 
if (null != html) { 
    final List<FileRowData> fileRowDataList = document.getEmbeddedImagesList(fieldName); 
    if (null != fileRowDataList) { 
     final Matcher matcher = imgRegExp.matcher(html); 
     while (matcher.find()) { 
      String src = matcher.group(); 
      final String srcToken = "src=\""; 
      final int x = src.indexOf(srcToken); 
      final int y = src.indexOf("\"", x + srcToken.length()); 
      final String srcText = src.substring(x + srcToken.length(), y); 
      for (FileRowData fileRowData : fileRowDataList) { 
       final String srcImage = fileRowData.getHref(); 
       final String cidImage = ((AttachmentValueHolder) fileRowData).getCID(); 
       final String typeImage = ((AttachmentValueHolder) fileRowData).getType(); 
       final String persistentName = ((AttachmentValueHolder) fileRowData).getPersistentName(); 

       // Add base 64 image inline (src="data:image/gif;base64,<name>") 
       if (srcText.endsWith(srcImage)) { 
        final String newSrc = src.replace(srcText, "data:" + typeImage + ";base64," + getBase64(persistentName)); 
        html = html.replace(src, newSrc); 
       } 
      } 
     } 
    } 
} 

下面是BASE64編碼圖像的getBase64()方法:

private String getBase64(final String fileName) { 
    String returnText = ""; 
    try { 
     BASE64Encoder base64Enc = new BASE64Encoder(); 
     ByteArrayOutputStream output = new ByteArrayOutputStream(); 
     base64Enc.encode(this.getEmbeddedImageStream(fileName), output); 
     returnText = output.toString(); 
    } catch (NotesException e) { 
     e.printStackTrace(); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 

    return returnText; 
} 

部分代碼來自emailBean by Tony McGuckin

+0

確實很酷。我使用內聯圖片激勵了你嗎?將正則表達式與Jericho解析器的性能和/或可維護性進行比較會有什麼意思 – stwissel 2013-10-12 06:38:53

2
+1

我剛剛發現了Tony McGuckin的emailBean中的getBodyHTML方法,地址爲http://openntf.org/XSnippets.nsf/snippet.xsp?id=emailbean-send-dominodocument-html-emails-cw-embedded-images-attachments-定製的HeaderFooter。它看起來很有趣。它也使用AttachmentValueHolder – 2013-02-27 20:24:21

1

可怕的黑客(你需要理清認證服務器名)

的SSJS(獲得從視圖源)

var unid = curRow.getUniversalID(); 
var body = getComponent("body1"); 
var magic = new demo.HTMLMagic(); 
magic.doMagic(database, unid, body); 

Java的

package demo; 


import java.io.ByteArrayOutputStream; 
import java.io.IOException; 
import java.io.InputStream; 
import java.io.OutputStream; 
import java.util.List; 
import org.apache.http.HttpHost; 
import org.apache.http.HttpResponse; 
import org.apache.http.HttpVersion; 
import org.apache.http.client.ClientProtocolException; 
import org.apache.http.client.HttpClient; 
import org.apache.http.client.methods.HttpGet; 
import org.apache.http.conn.ClientConnectionManager; 
import org.apache.http.conn.scheme.PlainSocketFactory; 
import org.apache.http.conn.scheme.Scheme; 
import org.apache.http.conn.scheme.SchemeRegistry; 
import org.apache.http.impl.client.DefaultHttpClient; 
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager; 
import org.apache.http.params.BasicHttpParams; 
import org.apache.http.params.HttpParams; 
import org.apache.http.params.HttpProtocolParams; 

import net.htmlparser.jericho.Attribute; 
import net.htmlparser.jericho.Attributes; 
import net.htmlparser.jericho.HTMLElementName; 
import net.htmlparser.jericho.OutputDocument; 
import net.htmlparser.jericho.Source; 
import net.htmlparser.jericho.StartTag; 
import lotus.domino.Database; 
import lotus.domino.NotesException; 

import com.ibm.misc.BASE64Encoder; 
import com.ibm.xsp.component.xp.XspInputRichText; 
import com.ibm.xsp.http.IMimeMultipart; 
import com.ibm.xsp.model.domino.wrapped.DominoRichTextItem; 

public class HTMLMagic { 

private HttpClient   httpClient = null; 
private HttpHost   httpHost = null; 
//TODO: that needs to be resolved smarter 
private static final String HOSTNAME = "localhost"; 

public void doMagic(final Database database, final String unid, final XspInputRichText body) throws NotesException, 
     ClientProtocolException, IOException { 
    final String docURL = "http://" + HOSTNAME + "/__" + database.getReplicaID() + ".nsf/0/" + unid + "/Body?OpenField"; 
    final String fixedHTML = this.fixHTML(docURL); 
    IMimeMultipart result = DominoRichTextItem.convertToMime("-- copied text--<br />" + fixedHTML); 
    body.setValue(result); 
} 

private String fixHTML(final String rawHTMLstring) throws ClientProtocolException, IOException { 
    HttpHost target = this.getHttpHost(); 
    HttpClient client = this.getHttpClient(); 
    HttpGet get = new HttpGet(rawHTMLstring); 
    HttpResponse response = client.execute(target, get); 
    InputStream data = response.getEntity().getContent(); 
    Source rawHTML = new Source(data); 
    OutputDocument outputDocument = new OutputDocument(rawHTML); 
    StringBuilder sb = new StringBuilder(); 
    String tagName = HTMLElementName.IMG; 
    String attName = "src"; 
    List<StartTag> links = rawHTML.getAllStartTags(tagName); 

    for (StartTag onelink : links) { 
     String href = onelink.getAttributeValue(attName); 
     if (href != null) { 
      String replace = this.urltoData(href); 
      if (replace != null) { 
       sb.setLength(0); 
       sb.append("<"); 
       sb.append(tagName); 
       sb.append(" "); 
       sb.append(attName); 
       sb.append("=\""); 
       sb.append(replace); 
       sb.append("\""); 
       Attributes atts = onelink.getAttributes(); 
       if (!atts.isEmpty()) { 
        for (int i = 0; i < atts.size(); i++) { 
         Attribute att = atts.get(i); 
         if (!att.getName().equals(attName)) { 
          sb.append(" "); 
          sb.append(att.getName()); 
          sb.append("=\""); 
          sb.append(att.getValue()); 
          sb.append("\" "); 
         } 
        } 
       } 
       sb.append(">"); 
       outputDocument.replace(onelink, sb.toString()); 
      } 
     } 
    } 
    return outputDocument.toString(); 
} 

private HttpClient getHttpClient() { 

    if (this.httpClient == null) { 

     // general setup 
     SchemeRegistry supportedSchemes = new SchemeRegistry(); 

     // Register the "http" protocol scheme, it is required 
     // by the default operator to look up socket factories. 
     supportedSchemes.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80)); 

     // prepare parameters 
     HttpParams params = new BasicHttpParams(); 
     HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1); 
     HttpProtocolParams.setContentCharset(params, "UTF-8"); 
     HttpProtocolParams.setUseExpectContinue(params, true); 

     ClientConnectionManager connMgr = new ThreadSafeClientConnManager(params, supportedSchemes); 
     this.httpClient = new DefaultHttpClient(connMgr, params); 
    } 
    return this.httpClient; 
} 

private HttpHost getHttpHost() { 
    if (this.httpHost == null) { 

     this.httpHost = new HttpHost(HOSTNAME, 80, "http"); 
    } 
    return this.httpHost; 
} 

private String urltoData(final String href) throws ClientProtocolException, IOException { 
    StringBuilder sb = new StringBuilder(); 
    sb.append("data:image/"); 
    sb.append(href.substring(href.lastIndexOf("FieldElemFormat=") + 1)); 
    sb.append(";base64,"); 

    // Here go the Image data 
    HttpHost target = this.getHttpHost(); 
    HttpClient client = this.getHttpClient(); 
    HttpGet get = new HttpGet(href); 
    HttpResponse response = client.execute(target, get); 
    InputStream data = response.getEntity().getContent(); 

    BASE64Encoder encoder = new BASE64Encoder(); 
    OutputStream output = new ByteArrayOutputStream(); 
    encoder.encode(data, output); 
    sb.append(output.toString()); 
    output.close(); 

    return sb.toString(); 
} 

} 

會好奇,如果你的作品。 Notes客戶端無法顯示內聯HTML圖像

+0

當然:您可以將它們變成適當的MIME部件,而不是完全內聯擠壓圖像數據。一般情況下采用相同的方法您也可以拉DXL而不是使用HTTP來獲取圖像的Base64版本。 – stwissel 2013-10-08 14:55:31

+0

由於這會將源文檔作爲後端的HTTP請求獲取,因此需要做更多的工作才能在源文檔受訪問保護的環境中「無縫地」工作。另外,我相信內聯圖片的鏈接應使用以下格式: 2013-10-11 08:36:02

+0

是的。您需要從HTTP會話中生成令牌。 Alternsate:DXL提供編碼的圖像 – stwissel 2013-10-11 09:01:03

相關問題