2013-02-27 5 views
7

Ich habe eine Lösung zum Kopieren von Rich-Text-Inhalten aus einem Dokument in MIME in einem anderen Dokument. Siehe http://per.lausten.dk/blog/2012/12/xpages-dynamically-updating-rich-text-content-in-a-ckeditor.html. Ich benutze dies in einer Anwendung als eine Möglichkeit für den Benutzer, Inhaltsvorlagen in ein neues Dokument einzufügen und den Inhalt im CKEditor on-the-fly erscheinen zu lassen.Kopieren von Rich Text und Bildern von einem Dokument zu MIME in einem anderen Dokument

Das Problem ist, dass Inline-Bilder nicht in den Kopiervorgang einbezogen sind - nur ein Verweis auf den temporären Speicher der Bilder. Dies bedeutet, dass die Bilder nur für den aktuellen Benutzer in der aktuellen Sitzung sichtbar sind. Also nicht sehr nützlich.

Wie kann ich Bilder hinzufügen?

Update 4. Oktober 2013: Ich bin immer noch auf der Suche nach einer Lösung für diese.

+1

Einige MIME-Magie ist erforderlich. Ich versuche etwas für dich zu kochen. – stwissel

Antwort

4

Endlich habe ich es geschafft. Es war viel einfacher und beinhaltete nicht einmal MIME. Der Trick bestand darin, die Image-Tags in der Arbeits HTML zu ändern, dem Base64-codiertes Bild enthalten, so dass der src-Tag dieses Format (hier mit einem gif als Beispiel gezeigt) verwenden:

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

Ich hatte bereits der Code erforderlich um den HTML aus dem Rich-Text-Feld zu bekommen (siehe my blog post bereits in meiner Frage erwähnt). Alles, was ich brauchte, war, die Bild-src-Tags durch das korrekte src-Format einschließlich des base64-codierten Bildes zu ersetzen.

dem folgenden Code wird das HTML und geht durch jede der enthaltenen Bilder und modifiziert die src-Tag:

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

Hier ist die getBase64() -Methode, die base64 ein Bild kodiert:

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

Ein Teil des Codes stammt aus der emailBean by Tony McGuckin.

+0

Cool in der Tat. Hat dich die Verwendung von Inline-Bildern inspiriert? Was wäre interessant, die Regex mit der Jericho-Parser-Leistung und/oder Wartbarkeit zu vergleichen – stwissel

2
+1

Ich habe gerade die getBodyHTML-Methode im EmailBean von Tony McGuckin entdeckt unter http://opennt.org/XSnippets.nsf/snippet.xsp?id=emailbean-send-dominodocument-html-emails-cw-embedded-images-attachments- Benutzerdefinierter Headerfooter. Es sieht interessant aus. Es verwendet AttachmentValueHolder auch –

1

Gruesome Hack (Sie müssen die Authentifizierung und Server aussortieren Namen)

die SSJS (immer die Quelle aus einer Sicht)

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

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

} 

Würde gespannt sein, ob das für Sie funktioniert. Der Notes-Client kann keine eingebetteten HTML-Bilder anzeigen

+0

Natürlich: Anstatt die Bilddaten komplett inline zu komprimieren, können Sie sie in richtige MIME Parts verwandeln. Im Allgemeinen der gleiche Ansatz. Sie könnten auch den DXL ziehen, anstatt HTTP zu verwenden, um zur Base64-Version des Bildes zu gelangen. – stwissel

+0

Da dies das Quelldokument als HTTP-Anforderung im Backend abruft, erfordert es mehr Arbeit, um "nahtlos" in einer Umgebung zu arbeiten, in der das Quelldokument zugriffsgeschützt ist. Außerdem glaube ich, dass Links zu Inline-Bildern das folgende Format verwenden sollten:

+0

Ja. Sie müssen das Token aus der HTTP-Sitzung generieren. Alternsate: DXL liefert die Bilder auch codiert – stwissel