Генерация встроенного изображения с помощью Java GWT
Я пытаюсь написать встроенное изображение с помощью Java GWT. Изображение, однако, не отображается:
<img src="data:unknown;base64,Pz9QAQSkZJRgABAQAAAQABAA9Q9AAUDBAcJCggFBQkGCAYGBggFBQUFCAgGBQYGBwUHBwUGBgUHChALBwgaCQUFDBUMDhERHxMfBxciGBYSGBAeEx4BBQUFCAcIDwgJCBIIDA4SEhISEhISEh4SEhIeEhIeHhISEh4eEhIeHh4SHh4eEhISEhISHh4eEhIeEh4eEhISHfz9ABEIAGAAYAMBIgACEQEDEQD9QAcAAACAQUBAAAAAAAAAAAAAAAAAQcCAwQGCAT9QAvEAACAQIEBAMHBQAAAAAAAAAAAQIDEQQFEiEGBzFBE1FyIjJhYnD9RRSPz9P0AGwEBAAIDAQEAAAAAAAAAAAAAAAECBAUHBgL9QAgEQEAAgEFAAMBAAAAAAAAAAAAAQIDBAUREiETMmExP0ADAMBAAIRAxEAPw9M0zKv1jbfz9bP0SUlJdkZtD0RV4JeRluEP0jP0tP0URVGNiorZSf9R9MP0dT0aVH9RznWgcfz9M379RET9Pz9GXo/EzNuW1FYUv9SXN1Wfz9Dj8/UpcHP05RjsQVM2S9XPz9Rf9Vb9Pz9SxxVL9JpDcWoNRzxuXYQXAYmFwAZV79WNiOfz9JX4vZEY8XoyPz9EnR6Lvz9X8PPz9My9vVv9P00c0lyRl8dOz9Ogr9P1GP0RBcG4YS79P07MF9dv09P1fRxwWk6R0hpLPz9XP1/Ux80cv1bf0CPz9OxH9UFwAP1qR3H9TP0CJg/Ffz9Pz9TlYVSkpxS39WL9S0T9a04cm8cZX4NSU39P0XEv0+1r9TPz9Pz9P1TTw9aEpWTv06Nfz9VP07NFn9cM3fF1eP1GAzRzP0hL0wSX9X04Jg5aZSL9P1rWr9Yv1fEi5ZOv1zMf0ND2UjJfz9Pz9HnZ9VoqFPymIPz9af1yD2QOIWJGP1ZQf1NXdmQBxXP0SUfz9P11aP0tMjv9SUpP1/Rf1BP1NTD9Yz9Pz9TT9X9HvX9XSwiT1sQT9NTT9W0zbv0mXv06P0ZP1RSfz9Rb9f0ADExgVQYAABcBDQ9cTH9Fgb9Sy79YzsPS0l8GE8gQAEAYCAYAAAAAAAAAPz9">
Мне кажется, что причина в том, что я неправильно кодирую с base64, или что кодировка неверна.
Ибо при возврате следующего кода картинки, которую я нашел в Интернете, все работает (так что нет, мой браузер не может отображать встроенные изображения):
<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[].
7 ответов
Jochen,
Я провел обширные тесты с различными библиотеками кодирования Base64:
- (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/
Протестированные браузеры: 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.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) = без разрывов, без URL-безопасных.
Кредитный балл: Вы можете заставить реализацию Google работать, если вы измените последние 2 символа карты символов: '$', '_' на '+', '/'.
Мой основной вывод заключается в том, что используемая вами библиотека Base64 содержит ошибки. Я предлагаю при поиске альтернативных реализаций попытаться сохранить поток байтов между изображением и кодером base64 в двоичном формате (byte[]). Строка может работать, если используется одно и то же кодирование / декодирование, но рискованно, если кодирование и декодирование выполняются в 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
}-*/;
- Этот блог JS очень помог.
- Этот ресурс отлично подходит для понимания работы завесы Javascript: XMLHTTPRequestObject
Мне нравится крепкий орешек, но я все это применил, и все же кодировка base64 не работает. Между JS и Java-оболочкой все еще существует проблема кодирования, и я не могу вернуть String обратно в правильный байт []. Перепробовал все возможные комбинации кодирования. Возможный путь - использовать base64 для req.responseText с использованием нативной библиотеки javascript и вернуть String для 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. Обратите внимание на некоторые предостережения: не будут работать в IE, учитывая, что они не поддерживают метод overrideMimeType в собственном 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 :-(");
}
}
Вот немного примера кода, когда мне нужно было создать сторону сервера Captcha в качестве средства защиты от ботов. Вы, кажется, знаете, что делаете, ради краткости, я опускаю настройку сервлета.
В любом случае есть 2 места, где я вижу, что все идет не так.
1) Ваш response.getText() не является правильной кодировкой изображения. Проблема только в том случае, если вы загружаете из БД или используете инструмент, который генерирует изображение как экземпляр класса Java Image.
2) Вы должны установить тип пантомимы. data:unknown должен быть допустимым MIME-типом, таким как data:image/jpeg (Ссылка http://www.w3schools.com/media/media_mimeref.asp). Если вы не установите MIME-тип, браузер должен угадать, и если он неправильно догадывается, что вы изображение не показывает.
Я предлагаю использовать установленный кодек с соответствующим типом mime (jpeg, gif, png), предполагая, что вы загружаете из байта [], а не из файла, и я также предлагаю использовать sun.misc.BASE64Encoder(). Encode(byte[]) так как вы можете быть уверены, что он работает как задумано.
Сторона клиента
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);
}
Кажется, что ваше изображение в кодировке String неверно, вы пропустили, включая тип содержимого изображения.
http://en.wikipedia.org/wiki/Data_URI_scheme
данные:[][; кодировка =][;base64],
Вы уверены, что полученные данные изображения верны? Поскольку вы запрашиваете изображение как текст, возможно, GWT обрабатывает двоичные данные перед вызовом обратного вызова (например, экранирование непечатаемых символов).
2 вероятные причины:
1) Ваш код на стороне сервера, считывающий изображение и отправляющий его по HTTP, портит двоичный формат изображения перед входом в Base64.encode(response.getText()). Если у вас есть доступ к серверной стороне, Base64. закодируйте свое изображение на сервере и просто передайте его:
callback.onSuccess("data:unknown;base64,"+ response.getText()); // response already in Base64
2) Если у вас нет доступа к серверной части, постарайтесь избегать преобразования String вызова 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 ...
Для чего стоит выложить мое решение для отправки изображений на сервер. Он использовал вызовы 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
}
});
}
// сервер
public String greetServer(String input) выдает 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
unknown
не является допустимым типом MIME. Ваш URI данных должен начинаться с data:image/png
или что-нибудь подходящее для изображения, которое будет отображаться. Неверный тип MIME, несмотря на file
Утилита не распознает декодированные данные с первого URL, который вы опубликовали. Что это за файл?