乔珍
我已经使用不同的base64编码库进行了广泛的测试:
- (gwt-base64) http://snipt.net/tweakt/gwt-base64/
- (google) http://pre.google.com/p/google-web-toolkit/source/browse/trunk/user/src/com/google/gwt/user/server/base64Utils.java?r=5962
(apache) http://commons.apache.org/prec/
经过测试的浏览器:Chrome 14.0.797.0 dev-m,Firefox 5
测试图像:jpeg,gif,png
测试代码:
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.enpre(dataAsSt); //doesn't work //google base64 impl String googlebase64 = base64Utils.tobase64(data); //apache base64 prec base64 base64prec = new base64(-1); String apachebase64 = base64prec.enpreToString(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)=没有断线,没有url安全的。
积分 :如果您将字符映射表的最后2个字符修改为“ $”,“ _”成“ +”,“ /”,则可以使google实现生效。
我的主要结论是您当前使用的base64库存在错误。我建议当您寻找替代实现时,请尝试以二进制格式(byte
[])保留图像与base64编码器之间的字节流。如果使用相同的编码/解码,则字符串可能会起作用,但是如果在两个不同的位置(例如客户端/服务器)进行编码和解码,则可能会有风险。
祝好运!
PS:试试这个:-)
<img />
编辑:进一步的研究
我花了比合理的时间更多的时间来寻找解决方案。GWT包装器不会让您获取原始数据,但是您可以使用JSNI强制浏览器获取二进制数据:
native String getBinaryResource(String url) ;
- 这个JS博客 大有帮助。
- 该资源非常适合理解Javascript幕背后的工作原理: XMLHTTPRequestObject
我乐于破解一个难题,但是我已经应用了所有这些,但是base64编码无法正常工作。JS和Java包装器之间仍然存在编码问题,我无法将String解码回正确的byte
[]。尝试了所有可能的编码组合。一种可行的方法是使用本机javascript库对req.responseText进行base64并将String返回给Java对应对象。
到目前为止,您的原始问题。
现在,看一些替代性想法和问题背后的要求:在研究期间,我发现base64通常用于 在服务器端 内联图像 ,
以避免额外的HTTP开销来在客户端获取图像。它似乎也是CSS内联的一种流行替代方法。
在此问题的上下文中,代码正在客户端(浏览器)上运行,并且这些原因不适用。使用基础
XMLHTTPRequest来获取图像二进制文件是在浏览器到服务器之间创建一个额外的HTTP请求。鉴于在客户端上下文中您显然拥有图像的URL(传递给该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) ;private void sendRequestBinary() { String url = URL.enpre("/Computer_File_030.gif"); String data = getBinaryResource(url); if (data != null) { // The secret sauce: Method to depre 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 :-("); }}


