Отображение изображения PNG в ответ на запрос jQuery AJAX
Можно ли отобразить изображение, возвращаемое вызовом jQuery AJAX, в основном потоке вашего HTML?
У меня есть скрипт, который рисует изображение с заголовком (изображение /PNG). Когда я просто вызываю его в браузере, изображение отображается.
Но когда я выполняю AJAX-вызов с jQuery для этого сценария, я не могу отобразить чистое изображение, у меня есть что-то с множеством странных символов. Это мой скрипт, который делает изображение с заголовком (image/PNG).
#!/usr/bin/perl
use strict;
use CGI;
use Template;
use CGI::Carp qw(fatalsToBrowser);
use lib qw(lib);
use GD;
my $cgi = new CGI;
my $id_projet = $cgi -> param('id_projet') ; #
# Create a new image
my $image = new GD::Image(985,60) || die;
my $red = $image->colorAllocate(255, 0, 0);
my $black = $image->colorAllocate(0, 0, 0);
$image->rectangle(0,0,984,59,$black);
$image->string(gdSmallFont,2,10,"Hello $id_projet ",$black);
# Output the image to the browser
print $cgi -> header({-type => 'image/png',-expires => '1d'});
#binmode STDOUT;
print $image->png;
Тогда у меня есть основной сценарий с вызовом AJAX внутри:
<script type="text/javascript" >
$(document).ready( function() {
$.ajax({
type: "POST",
url:'get_image_probes_via_ajax.pl',
contentType: "image/png",
data: "id_projet=[% visual.projet.id %]",
success: function(data){
$('.div_imagetranscrits').html('<img src="' + data + '" />'); },
} );
</script>
В моем HTML-файле у меня есть один div с class="div_imagetranscrits"
быть заполненным моим изображением.
Я не понимаю, что я делаю не так. Другое решение - заставить мой скрипт записать изображение на диск и просто получить путь для включения в src для его отображения. Но я думал, что можно получить изображение с заголовком image / PNG напрямую из запроса AJAX.
5 ответов
Вам нужно будет отправить изображение обратно в кодировке base64, посмотрите на это: http://php.net/manual/en/function.base64-encode.php
Затем в вашем ajax-вызове измените функцию успеха следующим образом:
$('.div_imagetranscrits').html('<img src="data:image/png;base64,' + data + '" />');
Способ 1
Вы не должны делать вызов ajax, просто поместите src элемента img в качестве URL-адреса изображения.
Это было бы полезно, если вы используете GET вместо POST
<script type="text/javascript" >
$(document).ready( function() {
$('.div_imagetranscrits').html('<img src="get_image_probes_via_ajax.pl?id_project=xxx" />')
} );
</script>
Способ 2
Если вы хотите отправить POST к этому изображению и сделать это так, как вы делаете (пытаясь проанализировать содержимое изображения на стороне клиента, вы можете попробовать что-то вроде этого: http://en.wikipedia.org/wiki/Data_URI_scheme
Вам нужно будет закодировать data
на base64, то вы могли бы поставить data:[<MIME-type>][;charset=<encoding>][;base64],<data>
в IMG SRC
как пример:
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==" alt="Red dot img" />
Для кодирования в base64:
- в простом JavaScript, см. Как вы можете кодировать строку в Base64 в JavaScript?
- в perl http://perldoc.perl.org/MIME/Base64.html
- в php http://php.net/manual/en/function.base64-encode.php
Это позволяет вам просто получить данные изображения и установить img src, что круто.
var oReq = new XMLHttpRequest();
oReq.open("post", '/somelocation/getmypic', true );
oReq.responseType = "blob";
oReq.onload = function ( oEvent )
{
var blob = oReq.response;
var imgSrc = URL.createObjectURL( blob );
var $img = $( '<img/>', {
"alt": "test image",
"src": imgSrc
} ).appendTo( $( '#bb_theImageContainer' ) );
window.URL.revokeObjectURL( imgSrc );
};
oReq.send( null );
Основная идея заключается в том, что данные возвращаются без изменений, они помещаются в большой двоичный объект, а затем создается URL для этого объекта в памяти. Смотрите здесь и здесь. Обратите внимание на поддерживаемые браузеры.
Благодаря приведенным выше ответам и после еще нескольких поисков мы смогли найти решение ниже для приложения Spring Boot.
HTML
<div class="row">
<div class="col-11" id='img_div'>
</div>
</div>
Javascript
function loadImage() {
$.ajax({
type: "GET",
url: contextPath+"/loadImage",
data: null,
dataType: 'text',
cache: false,
timeout: 600000,
success: function (data) {
$('#img_div').html('<img id="img" src="data:image/png;base64,' + data + '" />');
loadingBlockHide();
},
error: function (e) {
//handle error
}
});
}
Метод контроллера
@GetMapping("/loadImage")
@ResponseBody
private String loadImagefromExternalFolder(HttpServletRequest request,ModelMap map){
String encodedString = "";
try {
RandomAccessFile f = new RandomAccessFile("C:\\your_folder_path\\your_img.PNG", "r");
byte[] b = new byte[(int)f.length()];
f.readFully(b);
encodedString = Base64.getEncoder().encodeToString(b);
}catch (Exception e) {
// handle error
}
return encodedString;
}
Обновление на 2022 год: используйте большие двоичные объекты — вам больше не нужно тратить время и пропускную способность на преобразование в base64.
Вот пример из https://developer.mozilla.org/en-US/docs/Web/API/Response#fetching_an_image .
const image = document.querySelector('.my-image');
fetch('flowers.jpg')
.then(response => response.blob())
.then(blob => {
const objectURL = URL.createObjectURL(blob);
image.src = objectURL;
});