2011-06-20 56 views
6

我正在嘗試使用Java GWT編寫內聯圖像。圖像但不會顯示:使用Java gwt生成內聯圖像

<img src="data:unknown;base64,Pz9QAQSkZJRgABAQAAAQABAA9Q9AAUDBAcJCggFBQkGCAYGBggFBQUFCAgGBQYGBwUHBwUGBgUHChALBwgaCQUFDBUMDhERHxMfBxciGBYSGBAeEx4BBQUFCAcIDwgJCBIIDA4SEhISEhISEh4SEhIeEhIeHhISEh4eEhIeHh4SHh4eEhISEhISHh4eEhIeEh4eEhISHfz9ABEIAGAAYAMBIgACEQEDEQD9QAcAAACAQUBAAAAAAAAAAAAAAAAAQcCAwQGCAT9QAvEAACAQIEBAMHBQAAAAAAAAAAAQIDEQQFEiEGBzFBE1FyIjJhYnD9RRSPz9P0AGwEBAAIDAQEAAAAAAAAAAAAAAAECBAUHBgL9QAgEQEAAgEFAAMBAAAAAAAAAAAAAQIDBAUREiETMmExP0ADAMBAAIRAxEAPw9M0zKv1jbfz9bP0SUlJdkZtD0RV4JeRluEP0jP0tP0URVGNiorZSf9R9MP0dT0aVH9RznWgcfz9M379RET9Pz9GXo/EzNuW1FYUv9SXN1Wfz9Dj8/UpcHP05RjsQVM2S9XPz9Rf9Vb9Pz9SxxVL9JpDcWoNRzxuXYQXAYmFwAZV79WNiOfz9JX4vZEY8XoyPz9EnR6Lvz9X8PPz9My9vVv9P00c0lyRl8dOz9Ogr9P1GP0RBcG4YS79P07MF9dv09P1fRxwWk6R0hpLPz9XP1/Ux80cv1bf0CPz9OxH9UFwAP1qR3H9TP0CJg/Ffz9Pz9TlYVSkpxS39WL9S0T9a04cm8cZX4NSU39P0XEv0+1r9TPz9Pz9P1TTw9aEpWTv06Nfz9VP07NFn9cM3fF1eP1GAzRzP0hL0wSX9X04Jg5aZSL9P1rWr9Yv1fEi5ZOv1zMf0ND2UjJfz9Pz9HnZ9VoqFPymIPz9af1yD2QOIWJGP1ZQf1NXdmQBxXP0SUfz9P11aP0tMjv9SUpP1/Rf1BP1NTD9Yz9Pz9TT9X9HvX9XSwiT1sQT9NTT9W0zbv0mXv06P0ZP1RSfz9Rb9f0ADExgVQYAABcBDQ9cTH9Fgb9Sy79YzsPS0l8GE8gQAEAYCAYAAAAAAAAAPz9"> 

這接縫,我認爲這樣做的原因是,我用base64編碼錯誤的方式,或者說,字符集是錯誤的。

返回一個PIC我在網上找到的下面的代碼時,一切正常(所以它不是,我的瀏覽器無法顯示內嵌圖像):

<img src="data:unknown;base64,R0lGODlhDwAPAKECAAAAzMzM/////wAAACwAAAAADwAPAAACIISPeQHsrZ5ModrLlN48CXF8m2iQ3YmmKqVlRtW4MLwWACH+H09wdGltaXplZCBieSBVbGVhZCBTbWFydFNhdmVyIQAAOw=="> 

這是我如何產生我的圖片代碼。我打開一個URL,並嘗試爲Base64編碼的結果:

try { 
    IoProvider.get().makeRequestAsText(url, 
     new ResponseReceivedHandler<String>() { 
      public void onResponseReceived(ResponseReceivedEvent<String> event) { 
      final Response<String> response = event.getResponse(); 
      if (response.getStatusCode() == HTTP_OK){ 
      callback.onSuccess("data:unknown;base64," 
       + Base64.encode(response.getText())); 
      } 
      } 
     }, options); 
} catch ... 

那以base64編碼器使用:http://snipt.net/tweakt/gwt-base64/

任何想法,爲什麼生成的圖像是不是有效?

編輯:

根據你的回答,我重寫了我的代碼。這裏是如何看起來像現在:

IoProvider.get().makeRequest(url, 
    new ResponseReceivedHandler<Object>() { 
    public void onResponseReceived(ResponseReceivedEvent<Object> event) { 
     final Response<Object> response = event.getResponse(); 
     if (response.getStatusCode() == HTTP_OK) { 

      // not working 
      callback.onSuccess("data:image/jpeg;base64," 
       + Base64Utils.toBase64(response.getText().getBytes())); 

      // working image 
      // callback.onSuccess("data:unknown;base64,R0lGODlhDwAPAKECAAAAzMzM/////wAAACwAAAAADwAPAAACIISPeQHsrZ5ModrLlN48CXF8m2iQ3YmmKqVlRtW4MLwWACH+H09wdGltaXplZCBieSBVbGVhZCBTbWFydFNhdmVyIQAAOw=="); 
     } 
     } 
}, options); 

編輯的代碼產生以下代碼:

<img src="data:image/jpeg;base64,77+977+977+977+9ABBKRklGAAEBAAABAAEAAO+/ve+/vQDvv70ABQMEBwkKCAUFCQYIBgYGCAUFBQUICAYFBgYHBQcHBQYGBQcKEAsHCBoJBQUMFQwOEREfEx8HFyIYFhIYEB4THgEFBQUIBwgPCAkIEggMDhISEhISEhISHhISEh4SEh4eEhISHh4SEh4eHhIeHh4SEhISEhIeHh4SEh4SHh4SEhIe77+977+9ABEIAGAAYAMBIgACEQEDEQHvv73vv70AHAAAAgEFAQAAAAAAAAAAAAAAAAEHAgMEBggF77+977+9AC8QAAIBAgQEAwcFAAAAAAAAAAABAgMRBAUSIQYHMUETUXIiMmFice+/ve+/vRRS77+977+977+977+977+9ABsBAQACAwEBAAAAAAAAAAAAAAABAgQFBwYD77+977+9ACARAQACAQUAAwEAAAAAAAAAAAABAgMEBRESIRMyYTHvv73vv70ADAMBAAIRAxEAPwDvv70w77+9Myvvv71jbu+/ve+/vcWt77+9Eu+/vUlJdkZtDO+/vRHvv71eyIl5GW4R77+9I++/ve+/vS3vv73vv70U77+9FUY2KitlKO+/ve+/vRDvv70x77+9HUzvv70a77+9Uu+/vUTvv73Hp++/vWgc4a+m77+977+9M3/vv71ERe+/ve+/ve+/ve+/vRl6PxMzbu+/vW1FYUzvv71Jc3Va77+977+9Dj8/77+9Slwd77+9OUY7EO+/vVM277+9L1fvv73vv73vv73vv70Y77+977+9V++/ve+/ve+/ve+/ve+/vSxx77+9U++/ve+/vdKaQ3FqDUc8bu+/vXYQXAYmFwAZ77+9X++/ve+/vWNiOu+/ve+/vSV+L2RGPO+/vXoy77+977+977+9EnR6L++/ve+/ve+/vX8P77+977+977+9My9v77+9XO+/ve+/ve+/vTRzSXJGXx0477+977+9Ogvvv73vv73vv71GP0RB1bBuGO+/vS/vv73vv73vv707MFDvv71377+9Pe+/ve+/vV/vv70ccO+/vWnnrLpHSGkt77+977+9Xe+/vX9THzRz77+9W86y77+9Au+/ve+/ve+/vTsS77+977+9QXAB77+9akdy77+9Te+/vQLvv73GmD8W77+977+977+977+977+9TlYVSkpx77+9Lu+/ve+/vWPvv71LRe+/vWjvv704cm8cZX4NSU7vv73vv73vv70XE++/vT7Oq1vvv71N77+977+977+977+977+977+977+9U++/vTw9aEpWT++/vTo277+977+9Ve+/vTs0Wu+/vXHPjtufFO+/vV7vv73vv71GAzRz77+977+9ISzvv70w77+9Ju+/vVzvv704Jg5aZSPvv73vv73vv71ry6Fr77+9Y++/vV8SLlk777+9czLvv70ND2UjJu+/ve+/ve+/ve+/ve+/vR52fe+/vVoqFe+/vcKmIe+/ve+/vWrvv71yD2QOIWJG77+977+9WULvv71N77+9d2ZAHFfvv73vv70SUu+/ve+/ve+/ve+/vXVp77+9LTI877+977+9JSnvv73vv71/Ru+/vUHvv73vv71N77+9Me+/vWDvv73vv73vv73vv73vv73vv70177+977+9cO+/vR/Dtu+/vV0sIu+/vT1s77+9Be+/vTU177+9WO+/vTNv77+9Jl/vv70677+977+9Ge+/ve+/vVFK77+977+977+9F++/vXzvv70ADExgVQYAABcBDQDvv71xMu+/vRYH77+9Sy/vv71jOw9LSXwYTyBAAQBgIBgAAAAAAAAB77+977+9"> 

我也嘗試轉換的字符集:

try { 
    callback.onSuccess("data:image/jpeg;base64," 
    + Base64Utils.toBase64(response.getText().getBytes("ISO-8859-1"))); 
} catch (UnsupportedEncodingException e) { } 

其產生的代碼:

<img src="data:image/jpeg;base64,/f39/QAQSkZJRgABAQAAAQABAAD9/QD9AAUDBAcJCggFBQkGCAYGBggFBQUFCAgGBQYGBwUHBwUGBgUHChALBwgaCQUFDBUMDhERHxMfBxciGBYSGBAeEx4BBQUFCAcIDwgJCBIIDA4SEhISEhISEh4SEhIeEhIeHhISEh4eEhIeHh4SHh4eEhISEhISHh4eEhIeEh4eEhISHv39ABEIAGAAYAMBIgACEQEDEQH9/QAcAAACAQUBAAAAAAAAAAAAAAAAAQcCAwQGCAX9/QAvEAACAQIEBAMHBQAAAAAAAAAAAQIDEQQFEiEGBzFBE1FyIjJhYnH9/RRS/f39/f0AGwEBAAIDAQEAAAAAAAAAAAAAAAECBAUHBgP9/QAgEQEAAgEFAAMBAAAAAAAAAAAAAQIDBAUREiETMmEx/f0ADAMBAAIRAxEAPwD9MP0zK/1jbv39bf0S/UlJdkZtDP0R/V4JeRluEf0j/f0t/f0U/RVGNiorZSj9/RD9Mf0dTP0a/VL9RP3n/Wgc5v39M3/9REX9/f39GXo/EzNu/W1FYUz9SXN1Wv39Dj8//UpcHf05RjsQ/VM2/S9X/f39/Rj9/Vf9/f39/Sxx/VP9/ZpDcWoNRzxu/XYQXAYmFwAZ/V/9/WNiOv39JX4vZEY8/Xoy/f39EnR6L/39/X8P/f39My9v/Vz9/f00c0lyRl8dOP39Ogv9/f1GP0RBcG4Y/S/9/f07MFD9d/09/f1f/Rxw/Wk6R0hpLf39Xf1/Ux80c/1bsv0C/f39OxL9/UFwAf1qR3L9Tf0C/Zg/Fv39/f39TlYVSkpx/S79/WP9S0X9aP04cm8cZX4NSU79/f0XE/0+q1v9Tf39/f39/f1T/Tw9aEpWT/06Nv39Vf07NFr9cc7fFP1e/f1GAzRz/f0hLP0w/Sb9XP04Jg5aZSP9/f1r4Wv9Y/1fEi5ZO/1zMv0ND2UjJv39/f39HnZ9/VoqFf2mIf39av1yD2QOIWJG/f1ZQv1N/XdmQBxX/f0SUv39/f11af0tMjz9/SUp/f1/Rv1B/f1N/TH9YP39/f39/TX9/XD9H/b9XSwi/T1s/QX9NTX9WP0zb/0mX/06/f0Z/f1RSv39/Rf9fP0ADExgVQYAABcBDQD9cTL9Fgf9Sy/9YzsPS0l8GE8gQAEAYCAYAAAAAAAAAf39"> 

何我可以將響應傳遞給Base64編碼器,而不將其轉換爲字符串?

response.getData()是一個對象,我喜歡把它作爲byte []。

+0

我已經圍繞這一點,現在嘗試一些替代的想法:如果客戶端有圖像的URL,是t這裏是使用base64編碼嵌入它的原因,而不是動態更新圖像對象的url? – maasg

+0

直接鏈接圖像將導致需要403授權,因爲瀏覽器不會發送OAuth身份驗證標頭。不過,我會在JavaScript請求中設置它們。 – JochenJung

回答

6

約亨,

我已經做了廣泛的測試,以不同的Base64編碼庫:

測試代碼:

public static void main(String [] args) throws IOException { 
    File file = new File("./resources/so.png"); 
    BufferedInputStream bufRead = new BufferedInputStream(new FileInputStream(file)); 
    ByteBuffer buffer = ByteBuffer.allocate(30*1024) ; // x kb 
    byte[] c = new byte[1];  
    while ((bufRead.read(c))>0) { //1 byte/time to avoid buffer arithmetics 
     buffer.put(c); 
    } 
    byte[] data = new byte[buffer.position()]; 
    buffer.flip(); 
    buffer.get(data); 
    String dataAsSt = new String(data); // transform the data to a string -- encoding error-prone 
    //gwt-base64 
    //String gwtBase64 = GwtBase64.encode(dataAsSt); //doesn't work 

    //google base64 impl 
    String googleBase64 = Base64Utils.toBase64(data); 

    //apache base64 codec 
    Base64 base64codec = new Base64(-1); 
    String apacheBase64 = base64codec.encodeToString(data); 

    System.out.println("Google:"+googleBase64); 
    System.out.println("Apache:"+apacheBase64); 
    //System.out.println("GWTb64:"+gwtBase64); 
} 

結論:

  • (GWT-的base64)沒有在所有的工作。它在我嘗試的每個圖像上失敗:java.lang.StringIndexOutOfBoundsException: String index out of range。請注意,我註釋掉了代碼。

  • (google)它產生的Base64編碼是瀏覽器無法理解的。

  • (apache)與此構造函數一起工作:new Base64(-1)= no breaklines,no url-safe。

信用點:你可以讓谷歌的執行工作,如果你修改字符映射表的最後2個字符:「$」,「_」到「+」,「/」。

我的主要結論是,你目前使用的Base64庫是越野車。 我建議,當你尋找替代實現時,嘗試以二進制格式(byte [])保留圖像和base64編碼器之間的字節流。如果使用相同的編碼/解碼,但字符串可能工作,但如果編碼和解碼在2個不同位置(如客戶端/服務器)完成,則風險較大。

祝你好運!

PS:試試這個:-)

<img src="data:unknown;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAkGBhQRERQSDxQVFRUWGR4YGRgYFhgdFxUcHxgYGR4fIBsYGysfICEvGhgZHy8sIyswLCwsISIxNTIrNSYsLC0BCQoKDgwOGQ8NGjUjHiQ1KikzMTEwMDUvKTU1NTArNTU1NSkxNDUwKjA1MSo1LCo1NTUsMDU0LDYvKTYpNjUpLP/AABEIAEMA8AMBIgACEQEDEQH/xAAbAAEAAwEBAQEAAAAAAAAAAAAABAUGBwMIAv/EAEMQAAEDAgQDBAUICAUFAAAAAAEAAgMEEQUGEiEHEzFBUWFxFCIygZEIFiNCcqGx0TRUkpOjssHwUlOCs+EVJjNiov/EABoBAQACAwEAAAAAAAAAAAAAAAAEBQECAwb/xAAjEQEAAgICAQQDAQAAAAAAAAAAAQIDEQQhMRMiUXFCcpEU/9oADAMBAAIRAxEAPwDuCIiAiLL57im5QfE4iMe20beRuN7f8Ljny+ljm+t6d+Ph9bJGPettQst88HenClMbQ3Xo1XJJ2uD3DsU3KePekxWefpGbO8R2O/vtWRzf9DiDZfsSfA2P8qg8nlT6NM2Ketxv6WXB4cTnyYM0d6nX26UiAorRTCIiAiIgIiICIiAiIgIiICIiAiIgIiICIiAiIgIi8KytZCwvkOlo6nz27FiZ15IjfhmcUzwYKp0ZjvG2wPUOv2kX2I/HvV/Q4lDVMPLcHtIs5p6i/YQo9TBS1rbEsf3EH12+XaFkcSylPSO5tM5zmje7dnt8wOo8vgqu+TkYbTaffSfjzCzpTBmrFY9l4/kvKtp34bVhzLlh3b/7N7Wnx/4K9s/vbK2nqIzdr2kfgbee5SPMArYxTVLfpCfo5Gj63ZcdncbK8wzJbeQI6pxf62sNBIDDYg2I3PXfsUDHinLF8eDulu/1n4W3+muG1M3I6vXqdflHyucDqeZTwv72Nv52sfvCnLxo6NsTGxxizW7Ad3xXsvQ0iYrEW8vNZJrN5mvjciIi3cxERAREQEREBERAREQEREBERAREQEREBERBV43mGOkDDMHeve2kX6W8fFeuK4Y2pjDHlwBIdsRf7x4rLcTvZp/N/wCDFLzdlyeq5Jgc0aGm93EG5t3DwWt49vjbas6lEqsgSN3hkDu7UNJ+Iuo2qvpv8wtH+tv9VA+aeJR+w53+mc/gSnKxaP8Az/i139Soc4ojuu4SoyzPVtSvMHxNh5tZURNDogAXsBBcXbeze1/HxWpwrE2VEQljvpN7XFjsbLJySTuwqodVgiQn6zQ02DmgdAL9qt8h/oUfm7+YqTipFao+W82s0CLI4rxIiinfT09PVVckW0gp4tTYz3OcSBfwXvh2fI54JpmU9WHQEB8JgcJgTbYN6ONjfY7D3Lq5tOi5ZwVzOXUwp3Q1Ti6WU84xuMI3vYyE7Hst3q9n4pRl720tHXVTY3FjpIYCWBwNiAXEE2Pcg2yKmyxmyDEI3SUxd6jtD2PaWyRu7nNPRUddxUgbK+Klp6usMR0yOpoS9jD2jVfc+SDT41jUNJC6epfojba7rE2uQBs0E9SpkcgcA5u4IuPI7rmXEjM0Nfl+onpi7Tqa1wc0tcxwkZdpB7QtpiGYoaGibUVLtLGsb03c4los1o7SUF2izmM55gpKEV1S2SNrgNMbmgSuJ3DdN9jbfc7DrZc9p/lGs1gy0MjIXGwkEmo/slgB9zkHZUXPc38X46EUsrIDPT1LdTZWyWtYjUNJadwCD17x2K9zvnePDaL0st5oJa1jQ4DXq32Nj9W56INKiwdTxaigw2GvqonRunvyoA4Oe8A9b2AAtYk9lx1us/h3ygWc1ja6ilpo5PZk1Fwt32Mbbj7N0HXEWM4hcSW4VFBKIue2YkDTIGiwaHA30m4IKysXygObPHHT4fNI2Rwa067Oce0Nbosfe4eNkHQcy52o8PDfTZmxl/stsXOcO/S0E28eih1XEzD4ooJZagNZUNLoiWP9YA6TsG7b964PnbNUNTjgnqIJHQxubG6F1tTgy4IFjaxdc9VYcXauGWHCpKWIwROikLIyACwcxu1h43KD6QRVOZ8zQ4fTPqakkMbsABdz3Ho1o7yuXxfKOZqBkoZGwk2DxICf2SwNv4akHZkXO83cYY6KOlnihNRBVNLmyCTTYtIuC0tO9j8bjsVznriBHhlGyq0c3mOa1jQ7Tq1NLr3sdtIv8EGrRZZ+f4hhP/VA0lnL16NQvqvp0arddW17L0yBnA4pS+kmEwtLy1oL9WoC1zfSO249yCs4nezT+b/wYpWactz1L43QOAAYAbuI3uT2eal5xy5JViIRFo0F19RPbp7h4KnGVcR/Wv4j/wAlkQfmFWf42/vHfknzCrP8bf3jvyU75rYj+tfxH/knzWxH9a/iP/JBLrMNkp8JljmILhc3BJ6vBG5VhkP9Cj83fzFUM+T697S19QHNPUF7yD9y1WWcLdTU7YpCC4E9Om5J7UGOosIxLDJ6v0Onhq4KiZ04vNy5WOf1adQII22V3ljOxqppaSpp30tVE0PdG5zXBzDtqa9uxF7KFLhWNQySejVVLURucXNFTG4PjBN7XisCB2f0UnKeT5oamauxCZs1VK0R/Rt0xRRg30tB3O4G5/NYFXwVkDcLc5xsBPMSe4B1yvfCs61lYwzYdh7HU5cdEk1QI3S2JBcGBhsL36r9ZayTVUUskDJoX4fI+R/Lcx3OZrB9UOGxF+9Q8Hyti+Hx+i0U9HJTtJ5ZnZJzI2kk2Og2PU/3sgosu1k7ajMUj2CKYQtfoY/UGvEMpBDrC56HotnwlpWMwik5YA1M1ut2uLjqJ8b7e5R8k5GnpKmunrJmVBq9FyG6SSA7UC3oB61gB2BQqPJ2J4fqhwmop3UpcXMjqWvLoNRuQ1zeov3/AJ3CRxqYBgtTYAbsO3eZW3KxjcXllrcPrsWhLMPceXTNcdon6W6JZG9Lu3Iv0G/ZvtcYyRV1OEy0dRVNmqJXB5kc3Sxvrh2kBovpFja/3BaHG8sx1lE6jn3a5gbcfVcALOHiCLoOYfKVe7k0QHs65Ce64ay33FyvuJFJCMtkAN0sihMfSwN2WI9xPncqXVcN5KzCmUOJStdNCfop47m1hZpcHWv6p0nv2N7rGDgfiUrWU1TiDTSsI0tDpHWHgw2F+652QRqXL7qzKTTa76d8kzO/S17tQ/YLj7lmavMMmMRYThjCdTPUefHVoa7x0wi/vK+j8FwCKlpWUkTfomN0WO+oHqT3kkknzXPuH/Bo4diD6qSRj2NDxC0atTdRsC64tcMuNu0oMjxrp3R4nh0EDGlkcUbYo3/+MnmloBueh0tB8FZZxwPHsTgEFTR0oa1we1zHtDmkAjYmQ7WK3nEnhvHi0TPX5U0V+XJa4sbXa4d1wDtuD71jY+FeMy6IqrFDyWOBGl8hd6p2IBAuR2XKCi4tYfNT4PhMNULSx6mOFwbWaANxt7Nl2vK1KxtFSBrQA2GPSLDb6MXt8T8VluKHDmbFIKaKGZodCSXOlvd92ht/Uba9xc7BbXCaQwwRROIJZG1hI6EtaG/0QcVzOP8AvCn+1F/tr8/KO/SKH7L/AOdi2OL8NJpscixNskQiYWEsOrWdLdJ7Lfep3FDhqMXjjLJBFNETpcQS0h1rg236gEH80GX+Ui53olKB7POdfz0G34uVrm+kiGV7BrdDaaFzOlg76MgjxuT8SpEXDOapwx9Fi1SZpeZrjmBc4xWaA327E/WuO4rHjgdiT2NpZsQb6I03DdUhA8oyLX99kFVTYIanKRfa7qed8rfs6tLvucT7lX0ta7HZMJw67g2CItlPda9z+7YweZK79heUoKehFBGDyuW6M36u1AhxPiSSVjeFnCV+FTzT1EkcjnMDI9Gr1Rqu4nUOps3p4oOPVmZJIcLmweS/MZV9LfVGrU3960H3r6SyVgfoVBTU9rFkY1fbPrO/+iVh8b4NGfGW14fGIDIyR8Z1ay5tr22tYlo+JXU0BERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREH/2Q=="/> 

編輯:進一步研究

我花了更多的時間比合理試圖找到一個解決方案。 GWT的包裝不會讓你得到的原始數據,但可以使用JSNI迫使瀏覽器以獲得二進制數據:

native String getBinaryResource(String url) /*-{ 
    // ...implemented with JavaScript     
    var req = new XMLHttpRequest(); 
    req.open("GET", url, false); // The last parameter determines whether the request is asynchronous -> this case is sync. 
    req.overrideMimeType('text/plain; charset=x-user-defined'); 
    req.send(null); 
    if (req.status == 200) {      
     return req.responseText; 
    } else return null 
}-*/; 

愛破解難題,但我已經應用於所有,然而,base64編碼是行不通的。 JS和Java包裝器之間仍然存在編碼問題,我無法將字符串解碼回正確的字節[]。嘗試了所有可能的編碼組合。一種可行的方法是使用原生JavaScript庫base64 req.responseText並將字符串返回給java對手。

到目前爲止您的原始問題。現在

,尋找一些另類的想法和你的問題背後的要求:在我的研究,我已經看到了Base64是經常使用在服務器端內聯圖像,以避免額外的HTTP開銷得到在客戶端的圖像。它似乎也是CSS內聯的一種流行替代方案。

在此問題的上下文中,代碼在客戶端(瀏覽器)上工作,並且這些原因不適用。使用底層XMLHTTPRequest來獲取您的映像二進制文件是從您的瀏覽器創建一個額外的HTTP請求到服務器。鑑於在客戶端上下文中,你顯然有圖像的URL(傳遞給IoProvider.get().makeRequest(*url*,...)是有原因的,我們不能讓瀏覽器通過簡單的動態更新,如果圖像對象:

(這可能不是最好的代碼示例,但它給你的圖片(對不起,雙關語;-))

void setImage(String url) { 
    final HTML imageHolder = new HTML(); 
    String imgTag = "<IMG src='"+url+"' />'"; 
    imageHolder.setHTML(imgTag); 
    RootPanel.get("imageContainer").add(imageHolder); // imageContainer is a div 
} 

編輯:堅果是破裂

終於找到了失蹤的最後一塊拼圖:如何正確解碼來自JavaScript字符串的二進制數據我需要注意的是:如果它們不支持本地XMLHTTPRequest上的overrideMimeType方法,它將無法在IE上運行。

native String getBinaryResource(String url) /*-{ 
    var req = new XMLHttpRequest(); 
    req.open("GET", url, false); // The last parameter determines whether the request is asynchronous. 
    req.overrideMimeType('text/plain; charset=x-user-defined'); 

    req.send(null); 
    if (req.status == 200) { 
     return req.responseText; 
    } else return null 
}-*/; 

private void sendRequestBinary() { 
    String url = URL.encode("/Computer_File_030.gif"); 
    String data = getBinaryResource(url); 
    if (data != null) { 
     // The secret sauce: Method to decode the binary data in the response string 
     byte[] binData = new byte[data.length()]; 
     for (int i=0;i<data.length();i++) { 
      binData[i] = (byte)(data.charAt(i) & 0xff); 
     } 
     final HTML imageHolder = new HTML(); 
     String base64=Base64Utils.toBase64(binData); 

     String imgTag = "<IMG src='data:image/gif;base64,"+base64+"' />'"; 
     imageHolder.setHTML(imgTag); 
      RootPanel.get("imageContainer").add(imageHolder); 
      errorLabel.setText("Base64:"); 
    } else { 
     errorLabel.setText("Another error :-("); 
    } 
} 
+0

感謝您的研究。但是我既不能使用Base64Utils也不能使用apacheBase64與客戶端GWT一起工作。 [錯誤]第317行:沒有源代碼可用於com.google.gwt.user.server類型。Base64Utils;你忘了繼承一個必需的模塊嗎? - 如果我將它包含在我的.gwt.xml文件中,它也不會起作用。這答案表明,它只能用於服務器端http://stackoverflow.com/questions/4740865/try-to-use-base64utils-but-gwt-compiler-fails/5067881#5067881 – JochenJung

+1

@JochenJung谷歌的代碼Base64的impl對我來說似乎很乾淨,可以被GWT js編譯器翻譯。你可以在你的構建中添加src代碼嗎?我已經完成了GWT,這是一段時間。我認爲這應該是可能的。 – maasg

+0

好主意。我現在可以使用Base64Utils.toBase64()並重寫$和_ to +和/。但是圖像仍然不顯示。我編輯了我的問題並將新輸出放在那裏。我也嘗試改變編碼。我認爲Base64編碼器很好,因爲你已經檢查過了。接下來的問題是,我無法訪問byte [],因爲它在原始圖像中。由於response.getText()接縫將其銷燬。 – JochenJung

0

你的圖像編碼字符串似乎是錯誤的,你錯過了包括圖像內容類型。

http://en.wikipedia.org/wiki/Data_URI_scheme

數據:[] [;字符集=] [; BASE64],

+0

你的意思是charset =參數?我試過數據:unknown; charset = utf-8; base64,並沒有工作。 – JochenJung

0

你確定你接收的圖像數據是正確的?由於您以圖片的形式請求圖片,可能GWT在調用回調之前處理二進制數據(例如轉義不可打印的字符)。

+0

是的,我創建了 JochenJung

0

unknown不是有效的MIME類型。您的數據URI應以data:image/png或適合要顯示的圖像開頭。儘管不正確的MIME類型,但file實用程序不能識別您發佈的第一個URL中的解碼數據。它應該是什麼樣的文件?

+0

While its not a valid mimetype most browsers are smart enough to look at file markers and figure out the mimetype so most likely the encoding is incorrect. – ClassicThunder

+0

I tired image/jpg image/png and image/gif. None of them worked. I don't think it is needed, since the picture working has "unknown" as well. – JochenJung

0

下面是我需要生成驗證碼服務器端作爲機器人威懾物時的一些示例代碼。你似乎知道你在做什麼,所以爲了簡明起見,我拋棄了servlet設置。

反正有2個地方我看到事情出錯了。

1)您的response.getText()不是正確的圖像編碼。如果從數據庫加載或使用生成圖像的工具作爲Java Image類的實例,則只會出現問題。

2)你必須設置一個MIME類型。 data:unknown必須是一個有效的mimetype,例如data:image/jpeg(參考http://www.w3schools.com/media/media_mimeref.asp)如果你沒有設置MIME類型,瀏覽器必須猜測,如果它猜錯了,你的圖片將不會顯示。我建議使用已建立的編解碼器與匹配的MIME類型(jpeg,gif,png),假設你是從一個字節[]而不是文件加載的,我也建議使用sun.misc.BASE64Encoder()。encode(字節[]),因爲您可以確保它按預期工作。

客戶機端

ThecoderslibraryGWT.loginService.capImage( 
     new AsyncCallback<String>() { 

    @Override 
    public void onFailure(Throwable caught) { 
     error.setHTML(caught.getMessage()); 
    } 

    @Override 
    public void onSuccess(String result) { 
     String base64EncodedImage = result;    
     img.setUrl("data:image/jpg;base64," + base64EncodedImage); 
     vp.setVisible(true); 
    } 
}); 


服務器端

/** 
* 64 Bit encoded captcha image 
*/ 
public String capImage() { 

    byte[] data = null; 

    // the output stream to render the captcha image as jpeg 
    ByteArrayOutputStream jpegOutputStream = new ByteArrayOutputStream(); 
    try {      
     // get the session id that will identify the generated captcha. 
     //the same id must be used to validate the response, the session id is a good candidate! 
     String captchaId = this.getThreadLocalRequest().getSession().getId(); 

     BufferedImage challenge = CaptchaServiceSingleton.getInstance().getImageChallengeForID(captchaId, this.getThreadLocalRequest().getLocale()); 

     // a jpeg encoder 
     JPEGImageEncoder jpegEncoder = JPEGCodec.createJPEGEncoder(jpegOutputStream); 

     jpegEncoder.encode(challenge); 


     ByteArrayOutputStream os = new ByteArrayOutputStream(); 
     ImageIO.write(challenge, "jpg", os); 
     data= os.toByteArray();   

    } catch (IllegalArgumentException e) { 
     e.printStackTrace(); 
     throw new IllegalArgumentException("Unable to create validation image."); 
    } catch (CaptchaServiceException e) { 
     e.printStackTrace(); 
     throw new IllegalArgumentException("Unable to create validation image."); 
    } catch (IOException e) { 
     e.printStackTrace(); 
     throw new IllegalArgumentException("Unable to create validation image."); 
    } 

    return new sun.misc.BASE64Encoder().encode(data); 
} 
+0

I forgot to mention that my code is client side only. The server side is google contacts. I'm retrieving a picture from there. I read it with GWT generated javascript. I can not link the picture URL directly, sinct that would cause 403 Auth required. The javascript sends OAuth headers, when requesting the file, which returns the image data to me. Since Javascript can not write files, I then need to pass the image code as an inline-image. – JochenJung

+0

sun.misc.BASE64Encoder seams to work server side only. Using image/jpeg did not help. I guess, the problem is with the String conversion, or the Base64 encoding. But I already tried two different Base64encoding classes. – JochenJung

0

2可能原因:

1)你的服務器端代碼通過HTTP讀取圖像併發送它與搞亂在輸入Base64.encode(response.getText())之前編碼圖像的二進制格式。如果你已經訪問服務器端,Base64.encode服務器上您的圖像,只是將其穿過:

callback.onSuccess("data:unknown;base64,"+ response.getText()); // response already in Base64 

2)如果您沒有訪問到服務器端,儘量避免字符串翻譯response.getText()調用。

new ResponseReceivedHandler<byte[]>() { 
    public void onResponseReceived(ResponseReceivedEvent<byte[]> event) { 
     final Response<byte[]> response = event.getResponse(); 
      if (response.getStatusCode() == HTTP_OK){ 
       callback.onSuccess("data:unknown;base64," + Base64.encode(**response.getData()**)); 
      } 
     } 
    }, options); 
} catch ... 
+0

Unfortunalety I don't have access to the server. Its a google contacts picture, I'm trying to access. To request the URL containing the picture I have to send OAuth headers (which works). Since my code runs client side only, I need to use inline-images (JavaScript can't store files). – JochenJung

+0

How can I avoid the string translation? Afaik there is onyl IoProvider.get().makeRequestAsText() and no IoProvider.get().makeRequestAsByte – JochenJung

+0

@JochenJung have you tried: public void makeRequest(final String url, final ResponseReceivedHandler處理程序);然後檢查響應中對象的類型 response = event.getResponse();我強烈的印象是將圖像流轉換爲getText()方法中與內容混淆的字符串的內部編碼過程。 – maasg

0

爲什麼它的價值我會發布我的解決方案發送圖像到服務器。它使用了我讀過的你不能使用的RPC調用,但也許它有幫助。

//客戶

public void onModuleLoad() { 
    HTML html = new HTML(
      "<img src=\"data:image/png;base64, iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABGdBTUEAALGP C/xhBQAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9YGARc5KB0XV+IA AAAddEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIFRoZSBHSU1Q72QlbgAAAF1J REFUGNO9zL0NglAAxPEfdLTs4BZM4DIO4C7OwQg2JoQ9LE1exdlYvBBeZ7jq ch9//q1uH4TLzw4d6+ErXMMcXuHWxId3KOETnnXXV6MJpcq2MLaI97CER3N0 vr4MkhoXe0rZigAAAABJRU5ErkJggg==\" alt=\"Red dot\">"); 

    RootPanel.get().add(html); 

    greetingService.greetServer("", new AsyncCallback<String>() { 

     @Override 
     public void onSuccess(String result) { 
      HTML html = new HTML(
        "<img src=\"data:image/png;base64, "+ result + "\" alt=\"Window Logo\">"); 

      RootPanel.get().add(html); 
      RootPanel.get().add(new Label(result)); 

     } 

     @Override 
     public void onFailure(Throwable caught) { 
      // TODO Auto-generated method stub 

     } 
    }); 
} 

//服務器

公共字符串greetServer(字符串輸入)拋出:IllegalArgumentException - {

// BASE64Encoder 

    try{FileInputStream img = new FileInputStream(
      "C:\\icon_a.png"); 
    ByteArrayBuffer bab = new ByteArrayBuffer(0); 
    int eof = 0; 
    while (eof != -1) { 
     eof = img.read(); 
     bab.append(eof); 
    } 

    String rets = new BASE64Encoder().encode(bab.toByteArray()); 
     return rets; 

    }catch (Exception e) { 
     // TODO: handle exception 
    } 

    return null; 
} 

PS:圖片是http://www.drweb.de/icons/twitter/pd_twitter_iconset/pd_twitter_iconset/PNG/256/icon_a.png