私はウェブカメラのスナップショットレコーダーを作ろうとしています。写真を撮ってajax/async-uploadでWPメディアライブラリにアップロードしてください。
メディアライブラリにビューを追加できました。録音もできます。生の画像データをBLOBかbase 64でエンコードされた文字列(data urlのような)で保存することができます
このデータをアップロードキューに入れる方法を教えてください。
どんな提案/さらなる読書/これが評価されてうまくいかない理由をよく説明した。
どうもありがとう、Joern
編集:これはこれまでのところ私のコードです。それ
WPメディアライブラリにパネルを追加します。
src="data:image/
で画像を表示します
ファイルのようなオブジェクトを生成し、それをアップロードキューに入れることを試みます。 (それは私が失敗したところです)
JS依存:githubリポジトリ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>
最後に私は自分で解決策を見つけました。
純粋なバイナリデータ(BLOBなど)をWPアップロードオブジェクトに渡す直接的な方法はありません。ファイルベースのオブジェクトのみが処理されます。私は別のXmlHttpRequestを作成しなければなりませんでした。 (単に$.ajax()
を使用しても機能せず、汚染された画像データになりました。)
画像データをasync-upload.phpに正常にアップロードした後、サーバーが応答したものと一緒に 'FileUploaded'イベントを発生させることができました。この後、画像がメディアライブラリに表示されました。
上記のコード例は、次のようになります(未テストであり、まだスケッチもあります)。
<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>
関数send_b64_data( b64data , filename , post_data , success_callback )
は次のようになります。
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);
}
}
実用的なコードはここで見つけることができます: https://github.com/mcguffin/say-cheese (あなたがMediaLibraryにウェブカメラスナップショットと貼り付けられたイメージを加えることを可能にするWPプラグイン)