Есть 2 подхода:
1. Клиентская сторона тяжелая
Необходимое условие
- the image server has to support the range HTTP header
- eg.
Range: bytes=0-1024
means you are requesting only the first 1024 bytes
- you have to know in advance how many bytes you want to request
- you can say 1/8th of full size, if you push that value from server side
- поэтому точный номер байта должен быть известен на стороне клиента
- если
Range
недействителен или не поддерживается, то сервер вернет изображение целиком, что является хорошим естественным «запасным вариантом».
Междоменные запросы: если HTML и изображения находятся в разных доменах.
Access-Control-Allow-Headers: "range"
должен быть установлен
Пример Apache .htaccess
на сервере образов:
<IfModule mod_headers.c>
Header set Access-Control-Allow-Origin "*"
Header set Access-Control-Allow-Headers: "range"
</IfModule>
- Если браузеру не удается выполнить запрос из-за неправильных настроек
CROS
, код возвращается, чтобы установить атрибут data-src
в атрибут src
.
Обзор
- request image with an
AJAX
request
- set
Range
header of AJAX
request to how many bytes you want to get back
- установите
mimeType
в открытый текст (чтобы мы могли позже закодировать его в base64)
- Base64 encode data and set it to image's src attribute (
<img src="data:image/jpeg;base64,...">
)
- beware for larger images this can be quite heavy on the client
- Если установка атрибута src не удалась по какой-либо причине (например, из-за неправильных настроек
CROS
), вернитесь назад, чтобы установить атрибут data-src
в атрибут src
.
Код
Это основано на замечательном ответе gaetanoM здесь: Получить изображение с помощью jQuery.ajax() и декодировать его в base64
// for each img, which has data-src and data-bytes attributes
$('img[data-src][data-bytes]').each(function(i,e){
$.ajax({
url: $(e).data('src'), // url of image
type: 'GET',
headers: {
'Range':'bytes=0-'+$(e).data('bytes') // Range header, eg. Range: bytes=0-1024
},
mimeType: "text/plain; charset=x-user-defined"
}).done(function( data, textStatus, jqXHR ) {
$(e).attr('src', 'data:image/jpeg;base64,' + base64encode(data)); // on success we set the base64 encoded data to the image's src attribute
}).always(function(){
// if setting the src failed for whatever reason, we fall back to set the data-src attribute to src attribute
if(!$(e).attr('src'))
$(e).attr('src', $(e).data('src'));
});
});
function base64encode(str) {
var CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
var out = "", i = 0, len = str.length, c1, c2, c3;
while (i < len) {
c1 = str.charCodeAt(i++) & 0xff;
if (i == len) {
out += CHARS.charAt(c1 >> 2);
out += CHARS.charAt((c1 & 0x3) << 4);
out += "==";
break;
}
c2 = str.charCodeAt(i++);
if (i == len) {
out += CHARS.charAt(c1 >> 2);
out += CHARS.charAt(((c1 & 0x3)<< 4) | ((c2 & 0xF0) >> 4));
out += CHARS.charAt((c2 & 0xF) << 2);
out += "=";
break;
}
c3 = str.charCodeAt(i++);
out += CHARS.charAt(c1 >> 2);
out += CHARS.charAt(((c1 & 0x3) << 4) | ((c2 & 0xF0) >> 4));
out += CHARS.charAt(((c2 & 0xF) << 2) | ((c3 & 0xC0) >> 6));
out += CHARS.charAt(c3 & 0x3F);
}
return out;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!-- total filesize is 35 933 bytes -->
<img data-src="http://shoepimper.com/doklist.com-logo.jpg" data-bytes="1900">
<img data-src="http://shoepimper.com/doklist.com-logo.jpg" data-bytes="2500">
<img data-src="http://shoepimper.com/doklist.com-logo.jpg" data-bytes="5600">
<!-- if data-bytes are erroneous the server will return the whole image -->
<img data-src="http://shoepimper.com/doklist.com-logo.jpg" data-bytes="error">
<!-- if CROS fails, then it falls back to set the data-src attribute to the src attribute -->
<img data-src="https://i.stack.imgur.com/QOPRf.jpg" data-bytes="error">
2. Тяжело на стороне сервера
Разрабатывая комментарий ProgressiveMonkey, вы можете легко обрезать данные изображения с помощью php или любого другого языка программирования на стороне сервера.
Обзор
- server side: trim the image data based on an url parameter
- клиентская сторона: измените этот параметр URL по своему усмотрению.
Код на стороне сервера
<?php
$div = isset($_GET['div']) && intval($_GET['div'])>1 ? intval($_GET['div']) : 1; // what fraction of the image shall we return
$img = 'doklist.com-logo.jpg';
$size = round(filesize($img) / $div); // calculating the size in bytes what we return
// setting the headers
header("Content-Type: image/jpeg");
header("Content-Length: $size");
$fp = fopen($img, 'r');
echo fread($fp, $size); // returning the necessary amount of bytes
fclose($fp);
?>
Примеры
Посмотрите здесь пример одного из логотипов нашего сайта (Doklist.com)
Пожалуйста, не стесняйтесь играть с параметром div
этого URL-адреса (также обратите внимание, что мой тестовый сервер может плохо справляться с возросшим трафиком): http://shoepimper.com/progressive-thumb.php?div=14
Чтение только 1/24 размера файла и возврат его как целого изображения: <img src="http://shoepimper.com/progressive-thumb.php?div=24">
![введите здесь описание изображения](https://i.stack.imgur.com/1BUya.jpg)
Чтение 1/14 изображения: <img src="http://shoepimper.com/progressive-thumb.php?div=14">
![введите здесь описание изображения](https ://i.stack.imgur.com/W1QlU.jpg)
Чтение 1/6 изображения: <img src="http://shoepimper.com/progressive-thumb.php?div=6">
![введите здесь описание изображения](https ://i.stack.imgur.com/evJud.jpg)
Чтение всего изображения (1/1) <img src="http://shoepimper.com/progressive-thumb.php?div=1">
![введите здесь описание изображения]( https://i.stack.imgur.com/QOPRf.jpg)
Если вам нужна помощь, чтобы определить, кодируется ли изображение прогрессивно или нет, используйте это: http://codepen.io/sergejmueller/full/GJKwv
Если у вас нет прямого доступа к изображениям, вам следует использовать прокси, то есть структура самого кода на самом деле не меняется, вы просто «открываете» удаленный файл.
person
Viktor Tabori
schedule
04.05.2017