Agregar elemento a la biblioteca de medios desde blob o dataUrl

2

Estoy tratando de construir un registrador de instantáneas de webcam. Debería tomar una foto y subirla a la biblioteca de medios WP a través de ajax / async-upload.

Ya me las arreglé para agregar una vista a la biblioteca de medios. La grabación también funciona. Puedo almacenar los datos de imagen en bruto en blob o en una cadena codificada en base 64 (como url de datos)

¿Cómo puedo poner estos datos en la cola de carga?

Cualquier sugerencia / lectura adicional / razones bien explicadas por las cuales esto no funcionará apreciado.

Muchas gracias, joern

EDITAR: Este es mi código hasta ahora. Es

  • agrega un panel a la biblioteca de medios WP.

  • muestra una imagen con src="data:image/

  • Intenta generar un objeto similar a un archivo y colocarlo en la cola de carga. (Ahí es donde estoy fallando)

Dependencia de JS: necesita github repo blueimp / JavaScript-Canvas-to-Blob

<script type="text/javascript">
(function($){
var media = wp.media,
    l10n = media.view.l10n = typeof _wpMediaViewsL10n === 'undefined' ? {} : _wpMediaViewsL10n;

// override router creation
media.view.MediaFrame.Post.prototype.browseRouter = function( view ) {
    view.set({
        upload: {
            text:     l10n.uploadFilesTitle,
            priority: 20
        },
        dataurltest: {
            text:     'DataUrl Test', 
            priority: 30
        },
        browse: {
            text:     l10n.mediaLibraryTitle,
            priority: 40
        }
    });
};

var bindHandlers = media.view.MediaFrame.Post.prototype.bindHandlers,
    dataUrlTest, frame;

media.view.MediaFrame.Post.prototype.bindHandlers = function() {
    // bind parent object handlers
    bindHandlers.apply( this, arguments );
    // bind our create handler.
    this.on( 'content:create:dataurltest', this.dataurltestContent, this );
    frame = this;
};
media.view.MediaFrame.Post.prototype.dataurltestContent = function( content ){
    // generate test content
    var state = this.state();
    this.$el.removeClass('hide-toolbar');
    dataUrlTest = new media.view.dataUrlTest({});
    content.view = dataUrlTest;
}


media.view.dataUrlTest = media.View.extend({
    // our test view
    tagName:   'div',
    className: 'data-url-test',

    initialize: function() {
        _.defaults( this.options, {

        });
        var self = this, 
            blob;


        // add image with data-url to panel content
        var b64Data = 'R0lGODdhUAA8AIABAAAAAP///ywAAAAAUAA8AAACS4SPqcvtD6' +
                'OctNqLs968+w+G4kiW5omm6sq27gvH8kzX9o3n+s73/g8MCofE' +
                'ovGITCqXzKbzCY1Kp9Sq9YrNarfcrvcLDovH5PKsAAA7',
            imageUrl = 'data:image/gif;base64,' + b64Data,
            $img = $('<img src="'+imageUrl+'" />')
                .appendTo(this.$el);
        // add a submit link
        $('<a href="#" class="test-send">Okay</a>')
            .insertAfter($img)
            .on('click',null,function(){
                // creating a blob would go like this:
                //blob = window.dataURLtoBlob && window.dataURLtoBlob($img.get(0).src)

                var file = new plupload.File(null,b64Data);
                file.name = 'test.gif';
                file.id = 'id'+(new Date()).getTime(); 

                var attributes = _.extend({
                    file:      file,
                    uploading: true,
                    date:      new Date(),
                    filename:  'test.gif',
                    menuOrder: 0,
                    uploadedTo: wp.media.model.settings.post.id,
                    type : 'image',
                    subtype : 'gif'
                }, _.pick( file, 'loaded', 'size', 'percent' ) );

                file.attachment = wp.media.model.Attachment.create( attributes );
                wp.Uploader.queue.add(file.attachment);
                frame.uploader.uploader.uploader.refresh();
                frame.uploader.uploader.uploader.start();
            });

    },
});

return;




})(jQuery);
</script>
    
pregunta Jörn Lund 16.01.2014 - 21:46

1 respuesta

4

Finalmente encontré una solución por mi cuenta.

No hay una forma directa de pasar datos binarios puros (como un blob) al objeto de carga WP. Sólo se procesarán los objetos basados en archivos. Tuve que crear un XmlHttpRequest separado. (El simple uso de $.ajax() no funcionó y dio como resultado datos de imagen contaminados).

Después de cargar con éxito los datos de la imagen a async-upload.php pude lanzar un evento 'FileUploaded', junto con lo que respondió el servidor. Después de esto, la imagen apareció en la biblioteca de medios.

El ejemplo de código anterior podría tener este aspecto (no probado y aún incompleto):

<script type="text/javascript">
(function($){
var media = wp.media,
    frame,
    l10n = media.view.l10n = typeof _wpMediaViewsL10n === 'undefined' ? {} : _wpMediaViewsL10n;

// override router creation
media.view.MediaFrame.Post.prototype.browseRouter = function( view ) {
    view.set({
        upload: {
            text:     l10n.uploadFilesTitle,
            priority: 20
        },
        dataurltest: {
            text:     'DataUrl Test', 
            priority: 30
        },
        browse: {
            text:     l10n.mediaLibraryTitle,
            priority: 40
        }
    });
};

var bindHandlers = media.view.MediaFrame.Post.prototype.bindHandlers,
    dataUrlTest, frame;

media.view.MediaFrame.Post.prototype.bindHandlers = function() {
    // bind parent object handlers
    bindHandlers.apply( this, arguments );
    // bind our create handler.
    this.on( 'content:create:dataurltest', this.dataurltestContent, this );
    frame = this;
};
media.view.MediaFrame.Post.prototype.dataurltestContent = function( content ){
    // generate test content
    var state = this.state();
    this.$el.removeClass('hide-toolbar');
    dataUrlTest = new media.view.dataUrlTest({});
    content.view = dataUrlTest;
}


media.view.dataUrlTest = media.View.extend({
    // our test view
    tagName:   'div',
    className: 'data-url-test',

    initialize: function() {
        _.defaults( this.options, {

        });
        var self = this, 
            blob;

        // add image with data-url to panel content
        var b64Data =   'iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAMAAADXqc3KAAAAGXRFWHRTb2Z0d2F'+
                        'yZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyRpVFh0WE1MOmNvbS5hZG9iZS54bX'+
                        'AAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTe'+
                        'k5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8i'+
                        'IHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjA'+
                        'xMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPS'+
                        'JodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gP'+
                        'HJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8v'+
                        'bnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmF'+
                        'kb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG'+
                        '9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yV'+
                        'G9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoTWFjaW50b3NoKSIgeG1wTU06SW5z'+
                        'dGFuY2VJRD0ieG1wLmlpZDpGN0NENTMwNzdCNzcxMUUzQTBFQzg3RURFQTJCNTM'+
                        '5QiIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDpGN0NENTMwODdCNzcxMUUzQT'+
                        'BFQzg3RURFQTJCNTM5QiI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0Y'+
                        'W5jZUlEPSJ4bXAuaWlkOkY3Q0Q1MzA1N0I3NzExRTNBMEVDODdFREVBMkI1MzlC'+
                        'IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOkY3Q0Q1MzA2N0I3NzExRTNBMEV'+
                        'DODdFREVBMkI1MzlCIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+ID'+
                        'wveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+wqqcoQAAAAZQTFRFAAAA/'+
                        '///pdmf3QAAABFJREFUeNpiYBgFo4D6ACDAAAJYAAFvc4UPAAAAAElFTkSuQmCC',
            imageUrl = 'data:image/png;base64,' + b64Data,
            $img = $('<img src="'+imageUrl+'" />')
                .appendTo(this.$el);
        // add a submit link
        $('<a href="#" class="test-send">Okay</a>')
            .insertAfter($img)
            .on('click',null,function(){
                // creating a blob would go like this:
                //blob = window.dataURLtoBlob && window.dataURLtoBlob($img.get(0).src)

                // create and add item to upload queue
                var file = {}; 
                var attributes = {
                    file:      file,
                    uploading: true,
                    date:      new Date(),
                    filename:  'test.png',
                    menuOrder: 0,
                    uploadedTo: wp.media.model.settings.post.id,
                    type : 'image',
                    subtype : 'png',
                    loaded : 0,
                    size : 100,
                    percent : 0
                };

                file.attachment = wp.media.model.Attachment.create( attributes );
                wp.Uploader.queue.add(file.attachment);

                var post_data = {
                    action   : wp.Uploader.defaults.multipart_params.action,
                    _wpnonce : wp.Uploader.defaults.multipart_params._wpnonce,
                    post_id  : wp.media.model.settings.post.id
                }

                 function upload_succes( xhr , httpStatus ) {
                    // this will update the uploaded image in the media library
                    frame.uploader.uploader.uploader.trigger('FileUploaded', file, {
                        response : xhr.responseText,
                        status : httpStatus
                    });
                }

                send_b64_data( b64data , attributes.filename , post_data , upload_succes );
            });

    },
});

return;




})(jQuery);
</script>

La función send_b64_data( b64data , filename , post_data , success_callback ) se vería así:

function send_b64_data( b64data , filename , post_data , success_callback ) {

    var boundary, dashdash, crlf, multipart_string,
        file_data_name, name, mime_type , xhr;

    // setup multipart
    boundary            = '----multipart_boundary'+(new Date().getTime().toString(32))+Math.random().toString(32);
    dashdash            = '--';
    crlf                = '\r\n';


    // build request payload
    multipart_string    = '';
    for ( name in post_data ) {
        multipart_string += dashdash + boundary + crlf +
            'Content-Disposition: form-data; name="' + name + '"' + crlf + crlf;
        multipart_string += unescape(encodeURIComponent(send_data[name])) + crlf;
    }

    // add image data
    mime_type       = 'image/png';
    file_data_name  = 'async-upload';
    multipart_string += dashdash + boundary + crlf +
        'Content-Disposition: form-data; name="' + wp.Uploader.defaults.file_data_name + '"; filename="' + filename + '"' + crlf +
        'Content-Type: ' + mime_type + crlf +
            crlf + atob( b64data ) + crlf +
            dashdash + boundary + dashdash + crlf;

    // build and send request
    xhr = new XMLHttpRequest()
    xhr.open("post", wp.Uploader.defaults.url, true);
    xhr.setRequestHeader('Content-Type', 'multipart/form-data; boundary=' + boundary);
    xhr.onreadystatechange = function() {
        var httpStatus, chunkArgs;
        if (xhr.readyState == 4 ) {
            try {
                httpStatus = xhr.status;
            } catch (ex) {
                httpStatus = 0;
            }
            if (httpStatus == 200) {
                // will load contents to file fake
                success_callback(xhr,httpStatus);
            } else if ( httpStatus >= 400 ) {
                // handle error
            }
        }
    }

    if (xhr.sendAsBinary) { // Gecko
        xhr.sendAsBinary(multipart_string);
    } else { // WebKit with typed arrays support
        var ui8a = new Uint8Array(multipart_string.length);
        for (var i = 0; i < multipart_string.length; i++) {
            ui8a[i] = (multipart_string.charCodeAt(i) & 0xff);
        }
        xhr.send(ui8a.buffer);
    }
}

El código de trabajo se puede encontrar aquí: enlace (El complemento WP le permite agregar instantáneas de la cámara web e imágenes pegadas en la biblioteca de medios)

    
respondido por el Jörn Lund 26.01.2014 - 19:49

Lea otras preguntas en las etiquetas