web-dev-qa-db-fra.com

Télécharger une image base64 avec Ajax

Mon client propose à l'utilisateur de choisir une image, de la redimensionner et de la redimensionner, puis de l'afficher (dans un élément DOM <img>).
Si la photo est correcte, l'utilisateur peut la télécharger sur le serveur afin de pouvoir la sauvegarder.

Je voudrais faire le téléchargement grâce à une demande Ajax.

J'ai trouvé des tonnes d'exemples sur Internet pour télécharger l'image d'origine} récupérée à partir du PC client. Par exemple:

$( '#my-form' )
  .submit( function( e ) {
    $.ajax( {
      url: 'http://Host.com/action/',
      type: 'POST',
      data: new FormData( this ),
      processData: false,
      contentType: false
    } );
    e.preventDefault();
  } );

Cela fonctionne correctement si je décide de télécharger l'image récupérée via la saisie de formulaire.

Dans mon cas, je veux télécharger l'image modifiée (enregistrée dans un élément <img>) au lieu de celle d'origine.
Cette image est stockée en tant qu’image base64 (Pour information: j’ai utilisé la bibliothèque croppie.js pour générer l’image).

Je ne sais pas comment télécharger cette image avec Ajax.

J'ai essayé de le télécharger en tant que paramètre standard, mais sur le serveur, img est une chaîne vide:

var url = 'http://Host.com/action/';
var data = {};
data.img = $('img#generated-image').attr('src');

$.ajax({url: url, type: "POST", data: data})
  .done(function(e){
    // Do something
  });
// RESULTS in a empty data.img on the server side.

Mon problème étant que le serveur a une chaîne vide lors de la récupération du paramètre "img". Je soupçonne que l’image est peut-être trop grosse pour être transmise au serveur ou à d’autres problèmes que je ne comprends pas ....

Je me demande donc quelle est la méthode appropriée pour envoyer une image base64 au serveur à l'aide d'une requête Ajax SANS à l'aide d'un formulaire.

Merci de votre aide.

MODIFIER

Semble être un problème de taille de paramètre xmlHTTP POST. J'ai essayé de réduire le nombre de caractères de la représentation sous forme de chaîne de l'image et le serveur est maintenant capable de la récupérer.

EDIT2

post_max_size est défini sur 8 Mo dans le fichier php.ini alors que la taille de l'image n'est que de 24 Ko. Donc, le problème n'est pas là.
J'utilise PHP avec le framework Symfony2.
Peut-être une limitation de Symfony2.

16
Nitseg

J'ai finalement décidé de convertir l'image base64 en un objet blob afin qu'il puisse être envoyé via une requête Ajax avec l'objet formData comme suit . t ne trouve pas la raison pour laquelle le paramètre base64 n’a pas été transmis (à cause de la taille limitée, à coup sûr).

La fonction base64ToBlob est basée sur cette réponse à une autre question .

function base64ToBlob(base64, mime) 
{
    mime = mime || '';
    var sliceSize = 1024;
    var byteChars = window.atob(base64);
    var byteArrays = [];

    for (var offset = 0, len = byteChars.length; offset < len; offset += sliceSize) {
        var slice = byteChars.slice(offset, offset + sliceSize);

        var byteNumbers = new Array(slice.length);
        for (var i = 0; i < slice.length; i++) {
            byteNumbers[i] = slice.charCodeAt(i);
        }

        var byteArray = new Uint8Array(byteNumbers);

        byteArrays.Push(byteArray);
    }

    return new Blob(byteArrays, {type: mime});
}

Mon code JS:

var url = "url/action";                
var image = $('#image-id').attr('src');
var base64ImageContent = image.replace(/^data:image\/(png|jpg);base64,/, "");
var blob = base64ToBlob(base64ImageContent, 'image/png');                
var formData = new FormData();
formData.append('picture', blob);

$.ajax({
    url: url, 
    type: "POST", 
    cache: false,
    contentType: false,
    processData: false,
    data: formData})
        .done(function(e){
            alert('done!');
        });

Dans Symfony2, je peux récupérer l'image grâce à:

$picture = $request->files->get('picture');
33
Nitseg

La réponse de Nitseg fonctionne bien. De plus, je voulais ajouter les lignes suivantes si vous devez utiliser le jeton d'authentification dans votre appel ajax. Encore une fois, jetez un coup d'œil à la réponse de Nitseg pour plus de détails en premier.

var formData = new FormData();
var token = "<YOUR-TOKEN-HERE>";
formData.append("uploadfile", mediaBlob);        

jQuery.ajax({
    url: url,
    type: "POST",
    cache: false,
    contentType: false,
    processData: false,
    data: formData,
    beforeSend: function (xhr){ 
        xhr.setRequestHeader("Authorization", "Bearer " + token); 
    }
})
.done((e) => {
    // It is done.
})
.fail((e) => {
    // Report that there is a problem!
}); 
1
omt66