Oui, c'est possible.
Il est basé sur le nouvel attribut html5 "download" des balises d'ancrage.
Le flux devrait être quelque chose comme ceci :
- charger l'image
- dessine l'image dans un canevas avec les limites de recadrage spécifiées
- récupérer les données de l'image depuis le canevas et en faire une
href
pour une balise d'ancrage dans le dom
- ajouter l'attribut de téléchargement (
download="desired-file-name"
) à cette a
élément C'est tout. Tout ce que l'utilisateur doit faire est de cliquer sur votre "lien de téléchargement" et l'image sera téléchargée sur son ordinateur.
Je reviendrai avec une démo quand j'en aurai l'occasion.
Mise à jour
Voici la démo en direct comme je l'ai promis. Il prend le logo de jsfiddle et coupe 5px de chaque marge.
Le code ressemble à ceci :
var img = new Image();
img.onload = function(){
var cropMarginWidth = 5,
canvas = $('<canvas/>')
.attr({
width: img.width - 2 * cropMarginWidth,
height: img.height - 2 * cropMarginWidth
})
.hide()
.appendTo('body'),
ctx = canvas.get(0).getContext('2d'),
a = $('<a download="cropped-image" title="click to download the image" />'),
cropCoords = {
topLeft : {
x : cropMarginWidth,
y : cropMarginWidth
},
bottomRight :{
x : img.width - cropMarginWidth,
y : img.height - cropMarginWidth
}
};
ctx.drawImage(img, cropCoords.topLeft.x, cropCoords.topLeft.y, cropCoords.bottomRight.x, cropCoords.bottomRight.y, 0, 0, img.width, img.height);
var base64ImageData = canvas.get(0).toDataURL();
a
.attr('href', base64ImageData)
.text('cropped image')
.appendTo('body');
a
.clone()
.attr('href', img.src)
.text('original image')
.attr('download','original-image')
.appendTo('body');
canvas.remove();
}
img.src = 'some-image-src';
Mise à jour II
J'ai oublié de mentionner qu'il y a bien sûr un inconvénient :(.
En raison de la politique d'origine identique appliquée aux images, si vous voulez accéder aux données d'une image (par la méthode canvas toDataUrl
).
Vous aurez donc toujours besoin d'un proxy côté serveur qui servira votre image comme si elle était hébergée sur votre domaine.
Mise à jour III Bien que je ne puisse pas fournir de démonstration en direct (pour des raisons de sécurité), voici un exemple de code php qui résout le problème de la politique d'origine identique :
fichier proxy.php
:
$imgData = getimagesize($_GET['img']);
header("Content-type: " . $imgData['mime']);
echo file_get_contents($_GET['img']);
De cette façon, au lieu de charger l'image externe directement depuis son origine :
img.src = 'http://some-domain.com/imagefile.png';
Vous pouvez le charger via votre proxy :
img.src = 'proxy.php?img=' + encodeURIComponent('http://some-domain.com/imagefile.png');
Et voici un exemple de code php pour enregistrer les données de l'image (base64) dans une image réelle :
fichier save-image.php
:
$data = preg_replace('/data:image\/(png|jpg|jpeg|gif|bmp);base64/','',$_POST['data']);
$data = base64_decode($data);
$img = imagecreatefromstring($data);
$path = 'path-to-saved-images/';
// generate random name
$name = substr(md5(time()),10);
$ext = 'png';
$imageName = $path.$name.'.'.$ext;
// write the image to disk
imagepng($img, $imageName);
imagedestroy($img);
// return the image path
echo $imageName;
Tout ce que vous avez à faire, c'est d'envoyer les données de l'image dans ce fichier et il enregistrera l'image sur le disque et vous renverra le nom de fichier de l'image existante.
Bien sûr, tout cela peut sembler un peu compliqué, mais je voulais vous montrer que ce que vous essayez de faire est possible.