2013-02-27 80 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

相关问题