2011-06-20 128 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,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"/> 

编辑:进一步研究

我花了更多的时间比合理试图找到一个解决方案。 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