2013-02-27 42 views
7

Tôi có giải pháp sao chép nội dung văn bản đa dạng thức từ một tài liệu sang MIME trong tài liệu khác. Xem http://per.lausten.dk/blog/2012/12/xpages-dynamically-updating-rich-text-content-in-a-ckeditor.html. Tôi sử dụng điều này trong một ứng dụng như là một cách để người dùng chèn các mẫu nội dung vào một tài liệu mới và có nội dung xuất hiện ngay lập tức trong CKEditor.Sao chép văn bản và hình ảnh phong phú từ một tài liệu sang MIME trong một tài liệu khác

Sự cố là hình ảnh nội tuyến không được bao gồm trong việc sao chép - chỉ là tham chiếu đến lưu trữ tạm thời hình ảnh. Điều này có nghĩa là hình ảnh chỉ hiển thị đối với người dùng hiện tại trong phiên hiện tại. Vì vậy, không phải rất hữu ích.

Tôi có thể bao gồm hình ảnh bằng cách nào?

Cập nhật 04 Tháng Mười 2013: Tôi vẫn đang tìm kiếm một giải pháp cho việc này.

+1

Một số ma thuật MIME là bắt buộc. Tôi cố gắng nấu một cái gì đó cho bạn. – stwissel

Trả lời

4

Cuối cùng tôi đã làm việc đó. Nó đơn giản hơn nhiều và thậm chí không liên quan đến MIME. Bí quyết là để sửa đổi các thẻ hình ảnh trong HTML làm việc để đưa các base64 image mã hóa để thẻ src có thể sử dụng định dạng này (ở đây hiển thị với một gif làm ví dụ):

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

Tôi đã có mã cần thiết để lấy HTML từ trường văn bản có định dạng (xem my blog post đã được đề cập trong câu hỏi của tôi). Vì vậy, tất cả những gì tôi cần là thay thế thẻ src hình ảnh bằng định dạng src chính xác bao gồm hình ảnh được mã hóa base64.

Các mã sau đây được HTML và đi qua từng hình ảnh bao gồm và sửa đổi thẻ 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); 
       } 
      } 
     } 
    } 
} 

Đây là getBase64() phương pháp mà base64 mã hóa một hình ảnh:

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; 
} 

Một số mã là từ emailBean by Tony McGuckin.

+0

Thực sự thú vị. Việc tôi sử dụng hình ảnh nội tuyến có truyền cảm hứng cho bạn không? Điều gì sẽ là thú vị khi so sánh regex với hiệu suất của trình phân tích cú pháp Jericho và/hoặc khả năng bảo trì – stwissel

2

Bạn có thể có được một xử lý cho hình ảnh inline bởi DominoDocument.AttachmentValueHolder, xem http://public.dhe.ibm.com/software/dw/lotus/Domino-Designer/JavaDocs/XPagesExtAPI/8.5.2/com/ibm/xsp/model/domino/wrapped/DominoDocument.AttachmentValueHolder.html

Tôi viết blog về file đính kèm trong các tài liệu ghi chép, xem http://www.domino-weblog.nl/weblogs/Domino_Blog.nsf/dx/xpages-tip-get-easily-access-to-your-attachments-in-java.htm

+1

Tôi vừa phát hiện ra phương thức getBodyHTML trong emailBean bởi Tony McGuckin tại http://openntf.org/XSnippets.nsf/snippet.xsp?id=emailbean-send-dominodocument-html-emails-cw-embedded-images-attachments- custom-headerfooter. Trông nó thật thú vị. Nó sử dụng AttachmentValueHolder quá –

1

Hack khủng khiếp (bạn cần phải sắp xếp ra xác thực và máy chủ tên)

các SSJS (nhận được nguồn tin từ một cái nhìn)

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(); 
} 

} 

Hãy tò mò nếu điều đó phù hợp với bạn. Ứng dụng Ghi chú không thể hiển thị hình ảnh HTML nội tuyến

+0

Tất nhiên: thay vì ép dữ liệu hình ảnh hoàn toàn nội tuyến, bạn có thể biến chúng thành các phần MIME thích hợp. Nói chung cách tiếp cận tương tự. Bạn cũng có thể kéo DXL thay vì sử dụng HTTP để đến phiên bản Base64 của hình ảnh. – stwissel

+0

Vì điều này tìm nạp tài liệu nguồn như một yêu cầu HTTP trong phần cuối, nó đòi hỏi một số công việc nhiều hơn để làm việc "liền mạch" trong một môi trường nơi tài liệu nguồn được truy cập được bảo vệ. Ngoài ra, tôi tin rằng các liên kết đến hình ảnh nội tuyến phải sử dụng định dạng sau:

+0

Có. Bạn cần tạo mã thông báo từ phiên HTTP. Thay thế: DXL cung cấp hình ảnh được mã hóa quá – stwissel