I’m trying to build a webcam snapshot recorder. It should take a picture and upload it to the WP media library via ajax / async-upload.
Already managed to add a view to the media library. Recording also works.
I can either store the raw image data in blob or in base 64 encoded string (like data url)
How can I put this data into the upload queue?
Any suggestion / further reading / well explained reasons why this won’t work appreciated.
Thanks a lot, joern
EDIT:
This is my code so far. It
-
adds a panel to WP media library.
-
displays an image with
src="data:image/
-
Tries to generate a file-like object and put it in the upload queue. (That’s where I’m failing)
JS-Dependency: Needs 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>
Finally I found a solution on my own.
There is no direct way to pass pure binary data (like a blob) to the WP upload object. Only File based objects will be processed.
I had to create a separate XmlHttpRequest. (Simply using
$.ajax()
did not work and resulted in polluted Image data.)After successfully uploading the image data to async-upload.php I was able to fire a ‘FileUploaded’ event, along with what the server responded. After this the image showd up in the media library.
The code example above could look like this (untested and still sketchy):
The function
send_b64_data( b64data , filename , post_data , success_callback )
would look like this:Working code can be found here: https://github.com/mcguffin/say-cheese
(WP Plugin allowing you to add webcam snapshots and pasted images to the MediaLibrary)