Upload WebP images [closed]
want to improve this question? Add details and make it clearer what problem is being solved by editing this post .
Closed 3 years ago .
improve this questionI would like to do something similar to what the following link does with the images of my site, using the webp format:
When I try to save the image by this link, by Chrome, it saves in webp format. If I try to save by another browser, it saves in jpg format. If I remove from the url the part after the"?", saves in jpg format in all browsers.
Does anyone know how this is done? If it's time to upload or display?
The site is made in PHP, using the Laravel framework.
2 answers
This is done during the request. The code captures the parameter v
(or the browser checks the request headers), checks if the image is in cache, if it is returned. In case it is not, you can do as follows.
On your server (I'll use Nginx
for example)
# Aqui eu informo que toda imagem em `jpg` deverá ser redirecionada para o arquivo `image.jpg`
location ~ \.jpg$ {
rewrite (.*) /image.php?$args last;
}
No PHP:
<?php
// Captura o nome da imagem que foi solicitada
$request_uri = preg_replace("/^\/([^\?]*).*/", "$1", $_SERVER['REQUEST_URI']);
// Abre a imagem no formato JPG
$image = imagecreatefromjpeg($request_uri);
// Adiciona o Header informando o Content-Type
header("Content-Type: image/webp");
// Converte a imagem para WEBP
imagewebp($image);
This happens in Chrome as it captures the extension through the
Content-Type
.
Demonstration Of A Temporary 1
Demonstration Of A Temporary 2
Original Image
This is done using Content negotiation using header Accept:
, as I explained in this answer:
In Chrome, Opera and other Chromium-based browsers have support for webp
so the header is passed like this by the browser when it requests the page:
GET /arquivos/ids/8043120-430-430/image-14d749d28e68b73ea65d4832318ba6d6.jpg?v=636408381268700000 HTTP/1.1
Host: shopfacil.vteximg.com.br
Connection: keep-alive
User-Agent: Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.119 Safari/537.36 OPR/51.0.2830.26
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
But when you access via Firefox for not having webp support will be accessed via so probably see that that in Accept:
has image/webp
:
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,**image/webp**,image/apng,*/*;q=0.8
Already in Firefox the browser requests like this:
GET /arquivos/ids/8043120-430-430/image-14d749d28e68b73ea65d4832318ba6d6.jpg?v=636408381268700000 HTTP/1.1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: pt-BR,pt;q=0.8,en-US;q=0.5,en;q=0.3
Connection:keep-alive
Host: shopfacil.vteximg.com.br
User-Agent: Mozilla/5.0 (Windows NT 6.3; Win64; x64; rv:58.0) Gecko/20100101 Firefox/58.0
Of course in PHP there is nothing native to the q-factor , but there are libs via PEAR like
Or use the script of this response but adjust it to the header Accept:
(which is used for mime-type), for example:
function AcceptHeader($name)
{
$qvalues = array(); // used to store values
if (empty($_SERVER[$name]) === false) {
$result = preg_match_all('/([a-z]{1,8}(-[a-z]{1,8})?)\s*(;\s*q\s*=\s*(1|0\.[0-9]+))?/i', $_SERVER[$name], $parsed);
if ($result && count($parsed[1])) {
$qvalues = array_combine($parsed[1], $parsed[4]);
// Define o valor para tipos sem q-value definido
foreach ($qvalues as &$val) {
if ($val === '') {
$val = 1;
}
}
// sort list based on value
arsort($qvalues, SORT_NUMERIC);
}
}
return $qvalues;
}
Example to get the Type header requested by browser:
$tipos = AcceptHeader('HTTP_ACCEPT');
Example for languages supported by the browser:
$idiomas = AcceptHeader('HTTP_ACCEPT_LANGUAGE');
But since the focus is mime-type, then it should use something like this:
$tipos = AcceptHeader('HTTP_ACCEPT');
//Filtra somente imagens
$tipos = array_filter($tipos, function($header, $qvalue) {
return stripos($header, 'image/') === 0;
}, ARRAY_FILTER_USE_BOTH);
//Pega a primeira chave
$tipos = reset($tipos);
$tipo = key($tipos);
//Se contiver imagem/webp
if ($tipo == 'image/webp') {
readfile('images/webp/image.webp');
} else {
readfile('images/jpg/image.jpg');
}
Of course it can be much simpler still, this all above is just a suggestion of how to deliver according to the browser or user preference the type of content, but you can choose to decide only to check if there is support independent of the priority of q-factor using preg_match
and regex , like this:
if (isset($_SERVER['HTTP_ACCEPT']) && preg_match('#[\s,;]image/webp[\s,;]#', $_SERVER['HTTP_ACCEPT'])) {
readfile('images/webp/image.webp');
} else {
readfile('images/jpg/image.jpg');
}