问题
I'm trying to write an inline-image using Java GWT. The image however does not display:
<img src="data:unknown;base64,Pz9QAQSkZJRgABAQAAAQABAA9Q9AAUDBAcJCggFBQkGCAYGBggFBQUFCAgGBQYGBwUHBwUGBgUHChALBwgaCQUFDBUMDhERHxMfBxciGBYSGBAeEx4BBQUFCAcIDwgJCBIIDA4SEhISEhISEh4SEhIeEhIeHhISEh4eEhIeHh4SHh4eEhISEhISHh4eEhIeEh4eEhISHfz9ABEIAGAAYAMBIgACEQEDEQD9QAcAAACAQUBAAAAAAAAAAAAAAAAAQcCAwQGCAT9QAvEAACAQIEBAMHBQAAAAAAAAAAAQIDEQQFEiEGBzFBE1FyIjJhYnD9RRSPz9P0AGwEBAAIDAQEAAAAAAAAAAAAAAAECBAUHBgL9QAgEQEAAgEFAAMBAAAAAAAAAAAAAQIDBAUREiETMmExP0ADAMBAAIRAxEAPw9M0zKv1jbfz9bP0SUlJdkZtD0RV4JeRluEP0jP0tP0URVGNiorZSf9R9MP0dT0aVH9RznWgcfz9M379RET9Pz9GXo/EzNuW1FYUv9SXN1Wfz9Dj8/UpcHP05RjsQVM2S9XPz9Rf9Vb9Pz9SxxVL9JpDcWoNRzxuXYQXAYmFwAZV79WNiOfz9JX4vZEY8XoyPz9EnR6Lvz9X8PPz9My9vVv9P00c0lyRl8dOz9Ogr9P1GP0RBcG4YS79P07MF9dv09P1fRxwWk6R0hpLPz9XP1/Ux80cv1bf0CPz9OxH9UFwAP1qR3H9TP0CJg/Ffz9Pz9TlYVSkpxS39WL9S0T9a04cm8cZX4NSU39P0XEv0+1r9TPz9Pz9P1TTw9aEpWTv06Nfz9VP07NFn9cM3fF1eP1GAzRzP0hL0wSX9X04Jg5aZSL9P1rWr9Yv1fEi5ZOv1zMf0ND2UjJfz9Pz9HnZ9VoqFPymIPz9af1yD2QOIWJGP1ZQf1NXdmQBxXP0SUfz9P11aP0tMjv9SUpP1/Rf1BP1NTD9Yz9Pz9TT9X9HvX9XSwiT1sQT9NTT9W0zbv0mXv06P0ZP1RSfz9Rb9f0ADExgVQYAABcBDQ9cTH9Fgb9Sy79YzsPS0l8GE8gQAEAYCAYAAAAAAAAAPz9">
It seams to me that the reason for this is, that I'm encoding it the wrong way with base64, or that the charset is wrong.
For when returning the following code of a pic I found on the web, everything works (so its not, that my browser can't display inline-images):
<img src="data:unknown;base64,R0lGODlhDwAPAKECAAAAzMzM/////wAAACwAAAAADwAPAAACIISPeQHsrZ5ModrLlN48CXF8m2iQ3YmmKqVlRtW4MLwWACH+H09wdGltaXplZCBieSBVbGVhZCBTbWFydFNhdmVyIQAAOw==">
Here is how I generate my pic-code. I open an url and try to base64-encode the result:
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 ...
Thats the base64 encoder I use: http://snipt.net/tweakt/gwt-base64/
Any ideas, why the generated image is not valid?
EDIT:
I rewrote my code a little, based on your answers. Here is how it looks like now:
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);
The edited code produces the following code:
<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">
I also tried converting the charset:
try {
callback.onSuccess("data:image/jpeg;base64,"
+ Base64Utils.toBase64(response.getText().getBytes("ISO-8859-1")));
} catch (UnsupportedEncodingException e) { }
Which produces that code:
<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">
How can I pass response to an Base64 encoder, without converting it to String?
response.getData() is an object and I like to have it as byte[].
回答1:
Jochen,
I've done extensive tests with different Base64 encoding libraries:
- (gwt-base64) http://snipt.net/tweakt/gwt-base64/
- (google) http://code.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/codec/
Tested browsers: Chrome 14.0.797.0 dev-m, Firefox 5
Test images: jpeg, gif, png
Test code:
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);
}
Conclusions:
(gwt-base64) Didn't work at all. It failed with:
java.lang.StringIndexOutOfBoundsException: String index out of range
on every image I tried. Note that I commented out the code.(google) The Base64 encoding it produces cannot be understood by the browser.
(apache) Works with this constructor: new Base64(-1) = no breaklines, no url-safe.
Credit point: You can make the google implementation work if you modify the last 2 character of the character map: '$', '_' into '+', '/'.
My main conclusion is that the Base64 library you are currently using is buggy. I suggest that when you look for alternative implementations, try to preserve the byte flow between the image and the base64 encoder in binary format (byte[]). String might work if the same encoding/decoding is used but is risky if the encoding and the decoding are done in 2 different places (like client/server).
Good luck!
PS: Try this one :-)
<img src="data:unknown;base64,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"/>
Edit: Further research
I've spent more time than reasonable trying to find a solution. The GWT wrapper will not let you get the raw data, but you can use JSNI to force the browser to get the binary data:
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
}-*/;
- This JS Blog helped a lot.
- This resource is excellent to understand the workings behind the Javascript curtain: XMLHTTPRequestObject
Love to crack a hard nut, but I've applied all that and yet, the base64 encoding is not working. There's still an encoding issue between the JS and the Java wrapper and I can't get the String decoded back into a correct byte[]. Tried all the possible encoding combinations. A possible way to go would be to base64 the req.responseText using a native javascript library and return the String to the java counterpart.
So far for your original question.
Now, looking at some alternative ideas and the requirements behind your question: During my research, I've seen that Base64 is very often used to inline images at the server side to avoid the extra HTTP overhead to get the images at the client. It seems to be a popular alternative for CSS inlining as well.
In the context of this question, the code is working on the client (browser) and those reasons don't apply. Using the underlying XMLHTTPRequest
to get your image binary is creating an additional HTTP request from your browser to the server. Given that in the client context you obviously have the URL of the image (being passed to IoProvider.get().makeRequest(*url*,...)
is there a reason why we could not let the browser to the job through a simple dynamic update if the image object:
(this might not be the best code sample, but it gives you the picture (sorry for the pun ;-) )
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
}
Edit:The nut is cracked
Finally found the last missing piece of the puzzle: How to correctly decode the binary data from the JavaScript string. Note some caveats: Won't work on IE given that they don't support the overrideMimeType method on the native XMLHTTPRequest.
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 :-(");
}
}
回答2:
Your image encoded String seems to be wrong, you have missed including the image content type.
http://en.wikipedia.org/wiki/Data_URI_scheme
data:[][;charset=][;base64],
回答3:
Are you sure that the image data you received are correct? Since you are requesting the image as text, maybe GWT process the binary data before calling your callback (e.g escaping the non printable chars).
回答4:
unknown
is not a valid MIME type. Your data URI should start with data:image/png
or whatever is appropriate for the image to be displayed. Incorrect MIME type notwithstanding, the file
utility does not recognize the decoded data from the first URL that you have posted. What kind of file is it supposed to be?
回答5:
Here's a bit of example code from when I needed to generate a Captcha server side as a bot deterrent. You seem to know what you are doing so for the sake of being concise I'm leaving out the servlet setup.
Anyways there are 2 places I see things going wrong.
1) Your response.getText() is not a correct image encoding. Only an issue if you're loading from a DB or using using a tool that generates an image as an instance of the Java Image class.
2) You have to set a mime type. data:unknown has to be a valid mimetype such as data:image/jpeg (Reference http://www.w3schools.com/media/media_mimeref.asp) If you don't set a mimetype the browser has to guess and if it guesses incorrectly you're image wont show.
I suggest using an established codec with a matching mime type (jpeg, gif, png) assuming you are loading from a byte[] not a file, and I also suggest using sun.misc.BASE64Encoder().encode(byte[]) since you can be sure it works as intended.
Client Side
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);
}
});
Server Side
/**
* 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);
}
回答6:
2 probable reasons:
1) Your server-side code reading the image and sending it through HTTP is messing with the encoding of the binary format of the image before entering to Base64.encode(response.getText()). If you've access to the server-side, Base64.encode your image on the server and just pass it through:
callback.onSuccess("data:unknown;base64,"+ response.getText()); // response already in Base64
2) If you don't have access to the server side, try avoiding the String translation of the response.getText() call.
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 ...
回答7:
for what its worth I'll post my solution for an sending images to the server. It used RPC calls which I have read you cant use, but maybe it helps.
//Client
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
}
});
}
//server
public String greetServer(String input) throws 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: the image is http://www.drweb.de/icons/twitter/pd_twitter_iconset/pd_twitter_iconset/PNG/256/icon_a.png
来源:https://stackoverflow.com/questions/6409587/generating-an-inline-image-with-java-gwt