web-dev-qa-db-fra.com

Comment obtenir un fichier ou un blob à partir d'une URL d'objet?

J'autorise l'utilisateur à charger des images dans une page via un glisser-déposer et d'autres méthodes. Quand une image est supprimée, j'utilise URL.createObjectURL à convertir en URL d'objet pour afficher l'image. Je ne révoque pas l'URL, je le réutilise.

Ainsi, lorsque vient le temps de créer un objet FormData afin que je puisse leur permettre de télécharger un formulaire contenant l'une de ces images, puis-je alors inverser cette URL d'objet dans un fichier Blob ou File afin que je puisse ensuite l'ajouter à un objet FormData?

101
BrianFreud

Comme gengkev y fait allusion dans son commentaire ci-dessus, il semble que le meilleur/seul moyen de procéder est d'utiliser un appel asynchrone xhr2:

var xhr = new XMLHttpRequest();
xhr.open('GET', 'blob:http%3A//your.blob.url.here', true);
xhr.responseType = 'blob';
xhr.onload = function(e) {
  if (this.status == 200) {
    var myBlob = this.response;
    // myBlob is now the blob that the object URL pointed to.
  }
};
xhr.send();

Mise à jour (2018): Dans les cas où ES5 peut être utilisé en toute sécurité, Joe propose ci-dessous une réponse plus simple basée sur ES5.

65
BrianFreud

Solution moderne:

let blob = await fetch(url).then(r => r.blob());

L'URL peut être une URL d'objet ou une URL normale.

33
user993683

Peut-être que quelqu'un trouve cela utile lorsque vous travaillez avec React/Node/Axios. Je l'ai utilisé pour ma fonctionnalité de téléchargement d'images Cloudinary avec react-dropzone sur l'interface utilisateur.

    axios({
        method: 'get',
        url: file[0].preview, // blob url eg. blob:http://127.0.0.1:8000/e89c5d87-a634-4540-974c-30dc476825cc
        responseType: 'blob'
    }).then(function(response){
         var reader = new FileReader();
         reader.readAsDataURL(response.data); 
         reader.onloadend = function() {
             var base64data = reader.result;
             self.props.onMainImageDrop(base64data)
         }

    })
8
spedy

Voir Obtention des données BLOB de la demande XHR qui indique que BlobBuilder ne fonctionne pas dans Chrome, vous devez donc utiliser:

xhr.responseType = 'arraybuffer';
4
Michel Floyd

Si vous affichez quand même le fichier dans un canevas, vous pouvez également convertir le contenu du canevas en objet blob.

canvas.toBlob(function(my_file){
  //.toBlob is only implemented in > FF18 but there is a polyfill 
  //for other browsers https://github.com/blueimp/JavaScript-Canvas-to-Blob
  var myBlob = (my_file);
})
2
Thilo

Malheureusement, la réponse de @ BrianFreud ne correspond pas à mes besoins, j'avais des besoins un peu différents et je sais que ce n'est pas la réponse à la question de @ BrianFreud, mais je la laisse ici parce que beaucoup de personnes sont venues ici avec le même besoin. J'avais besoin de quelque chose comme: "Comment obtenir un fichier ou un blob à partir d'une URL?".

J'ai un site Web qui utilise des images d'un stockage Amazon S3/Azure, et j'y stocke des objets nommés avec des identificateurs uniques:

exemple: http: //****.blob.core.windows.net/systemimages/bf142dc9-0185-4aee-a3f4-1e5e95a09bcf

Certaines de ces images doivent être téléchargées à partir de notre interface système. Pour éviter de transmettre ce trafic via mon serveur HTTP, cet objet ne nécessitant aucune sécurité (à l'exception du filtrage de domaine), j'ai décidé de demander directement au navigateur de l'utilisateur et d'utiliser un traitement local pour attribuer un nom réel au fichier. extension.

Pour ce faire, j’ai utilisé cet excellent article de Henry Algus: http://www.henryalgus.com/reading-binary-files-using-jquery-ajax/

1. Première étape: Ajouter un support binaire à jQuery

/**
*
* jquery.binarytransport.js
*
* @description. jQuery ajax transport for making binary data type requests.
* @version 1.0 
* @author Henry Algus <[email protected]>
*
*/

// use this transport for "binary" data type
$.ajaxTransport("+binary", function (options, originalOptions, jqXHR) {
    // check for conditions and support for blob / arraybuffer response type
    if (window.FormData && ((options.dataType && (options.dataType == 'binary')) || (options.data && ((window.ArrayBuffer && options.data instanceof ArrayBuffer) || (window.Blob && options.data instanceof Blob))))) {
        return {
            // create new XMLHttpRequest
            send: function (headers, callback) {
                // setup all variables
                var xhr = new XMLHttpRequest(),
        url = options.url,
        type = options.type,
        async = options.async || true,
        // blob or arraybuffer. Default is blob
        dataType = options.responseType || "blob",
        data = options.data || null,
        username = options.username || null,
        password = options.password || null;

                xhr.addEventListener('load', function () {
                    var data = {};
                    data[options.dataType] = xhr.response;
                    // make callback and send data
                    callback(xhr.status, xhr.statusText, data, xhr.getAllResponseHeaders());
                });

                xhr.open(type, url, async, username, password);

                // setup custom headers
                for (var i in headers) {
                    xhr.setRequestHeader(i, headers[i]);
                }

                xhr.responseType = dataType;
                xhr.send(data);
            },
            abort: function () {
                jqXHR.abort();
            }
        };
    }
});

2. Deuxième étape: Effectuer une demande en utilisant ce type de transport.

function downloadArt(url)
{
    $.ajax(url, {
        dataType: "binary",
        processData: false
    }).done(function (data) {
        // just my logic to name/create files
        var filename = url.substr(url.lastIndexOf('/') + 1) + '.png';
        var blob = new Blob([data], { type: 'image/png' });

        saveAs(blob, filename);
    });
}

Maintenant, vous pouvez utiliser le blob créé comme vous le souhaitez, dans mon cas, je veux le sauvegarder sur le disque.

3. Facultatif: enregistrez le fichier sur l'ordinateur de l'utilisateur à l'aide de FileSaver

J'ai utilisé FileSaver.js pour enregistrer sur le disque le fichier téléchargé. Si vous avez besoin d'accomplir cela, utilisez cette bibliothèque javascript:

https://github.com/eligrey/FileSaver.js/

J'espère que cela aidera les autres avec des besoins plus spécifiques.