Php $HTTP_原始_发布_数据和Wordpress媒体_处理_上传

Php $HTTP_原始_发布_数据和Wordpress媒体_处理_上传,php,ajax,wordpress,file-upload,canvas,Php,Ajax,Wordpress,File Upload,Canvas,因此,我正在制作一些东西,用户需要使用Wordpress内置的媒体上传API从画布元素(在前端)上传图像 我已使用API成功地从以下表单中输入的文件上载图像: <input type="file" name="async-upload" id="async-upload" size="40" /> ... <?php $new_attach_id = media_handle_upload( 'async-upload', $new_id ); ?> ... 我使用

因此,我正在制作一些东西,用户需要使用Wordpress内置的媒体上传API从画布元素(在前端)上传图像

我已使用API成功地从以下表单中输入的文件上载图像:

<input type="file" name="async-upload" id="async-upload" size="40" />
...
<?php $new_attach_id = media_handle_upload( 'async-upload', $new_id ); ?>

...
我使用自己的脚本保存了画布上的图像:

<script type="text/javascript">
...
var img = canvas.toDataURL("image/png");
...
ajax.send(img );
</script>
...
<?php 
$imageData=$GLOBALS['HTTP_RAW_POST_DATA'];
$filteredData=substr($imageData, strpos($imageData, ",")+1);
$unencodedData=base64_decode($filteredData);
$fp = fopen( 'saved_images/canv_save_test.png', 'wb' );
fwrite( $fp, $unencodedData);
...
?>

...
var img=canvas.toDataURL(“image/png”);
...
发送(img);
...
问题是,Wordpress的media\u handle\u upload()只接受用于上传的$文件数组的索引

所以问题是:如何将图像数据从HTTP_RAW_POST_数据传递给它?我可以让$_文件['tmp-name']指向它吗?我可以用另一个脚本作为中间步骤吗?我能放开打字机上的猴子直到他们找到答案吗

非常感谢任何帮助

谢谢, 凯恩

编辑:已解决

感谢@alex提供的文件内容建议,以及对我发布的另一个相关问题的回答,我现在有了这个工作。解决方案:在HTTP请求中发送未更改的base64图像数据,覆盖PHP生成的tmp_文件,并关闭WP的一些安全检查。不知道这有多安全,但以下是针对有相同问题的人的代码:

<script type="text/javascript">
$('#save').click(function() {

        // get image data from cavas
        var img = canvas.toDataURL("image/png");

        // open ajax request
        var ajax = new XMLHttpRequest();
        ajax.open("POST",script_url,false); 
        //ajax.open("POST","/dumpvars.php",false); // testing

        // set headers
        boundary_str = "AJAX-------------" + (new Date).getTime();
        ajax.setRequestHeader('Content-Type', "multipart/form-data; boundary=" + boundary_str);

        // callback for completed request
        ajax.onreadystatechange=function()
        {
            if (ajax.readyState == 4)
            { 
                // Write out the filename.
                $("#ajax_out").html("Response: "+ajax.responseText+" End Response");
            }
        }

        // BUILD REQUEST
        var boundary = '--' + boundary_str; 
        var request_body = boundary + '\n'
        // print all html form fields
        $('#save_form input').each(function(){ 
            request_body += 'Content-Disposition: form-data; name="' 
            + $(this).attr('name') + '"' + '\n' 
            + '\n' 
            + $(this).val() + '\n' 
            + '\n' 
            + boundary + '\n';
        });
        // make filename
        var filename = $('#save_form input[name="title"]').val();
        filename = filename.replace(/\s+/g, '-').toLowerCase(); // hyphenate + lowercase
        filename = encodeURIComponent(filename) + (new Date).getTime() + ".png";
        // add image
        request_body += 'Content-Disposition: form-data; name="async-upload"; filename="' 
            + filename + '"' + '\n'
        + 'Content-Type: image/png' + '\n' 
        + '\n' 
        + img
        + '\n' 
        + boundary;

        // Send request
        ajax.send(request_body);

    });
</script>

...


<?php
    // Get transmitted image data 
    $loc = $_FILES['async-upload']['tmp_name'];
    $file = fopen($loc, 'rb');
    $contents = fread($file, filesize($loc));
    fclose($file);
    // Decode image data
    $filteredData=substr($contents, strpos($contents, ",")+1);
    $unencodedData=base64_decode($filteredData);
    // Overwrite temp file
    file_put_contents($loc, $unencodedData);

    // Pass image data to WP Upload (attach to post)
    $override['test_upload'] = false; // Override WP's upload security test (rewriting tmp_name made it fail)
    $override['test_form'] = false;
    $new_attach_id = media_handle_upload( 'async-upload', $new_id, array() , $override );

?>

$(“#保存”)。单击(函数(){
//从cavas获取图像数据
var img=canvas.toDataURL(“image/png”);
//打开ajax请求
var ajax=new-XMLHttpRequest();
open(“POST”,script\u url,false);
//open(“POST”,“/dumpvars.php”,false);//测试
//设置标题
boundary_str=“AJAX-------------------”+(新日期).getTime();
setRequestHeader('Content-Type',“多部分/表单数据;boundary=“+boundary_str”);
//已完成请求的回调
ajax.onreadystatechange=function()
{
if(ajax.readyState==4)
{ 
//写出文件名。
$(“#ajax_out”).html(“响应:+ajax.responseText+“结束响应”);
}
}
//构建请求
变量边界='--'+boundary_str;
var请求\u body=boundary+'\n'
//打印所有html表单字段
$('#保存表单输入')。每个(函数(){
请求_body+='内容处置:表单数据;名称='
+$(this.attr('name')+'“+”)\n
+“\n”
+$(this).val()+'\n'
+“\n”
+边界+'\n';
});
//生成文件名
var filename=$('#保存表单输入[name=“title”]”)。val();
filename=filename.replace(/\s+/g,“-”).toLowerCase();//连字符+小写
filename=encodeURIComponent(文件名)+(新日期).getTime()+“.png”;
//添加图像
请求\u body+=“内容处置:表单数据;name=“异步上传”;filename=“”
+文件名+''''+'\n'
+'内容类型:image/png'+'\n'
+“\n”
+img
+“\n”
+边界;
//发送请求
发送(请求\正文);
});
...

你可以
file\u put\u contents()
将数据放在某个地方,然后制作你自己的人造
$\u文件
数组来欺骗WordPress函数。

你可以
file\u put\u contents()
将数据放在某个地方,然后制作你自己的人造
$\u文件
数组来欺骗WordPress的功能。

我将更新这篇文章,说明我是如何做的,以防其他人正在努力将画布数据保存到WordPress作为文章附件

我使用了media\u sideload\u image函数,而不是使用media\u handle\u upload,您必须使用$\u FILES数组。为了做到这一点,您只需将画布图像保存到服务器上的一个文件夹中,然后将该URL传递给media_sideload_image和post ID即可。它会将该文件附加到您的帖子中,并将图像复制到您的上载文件夹中。您可以在服务器上创建TEMP_UPLOADS文件夹来存储上载的文件,然后在成功将其附加到帖子后手动删除

define('UPLOAD_DIR', 'path/to/termp-folder/');
$img = $_POST['img'];
$post_id = $_POST['postId'];
$post_id = (int) $post_id;
$img = str_replace('data:image/jpeg;base64,', '', $img);
$img = str_replace(' ', '+', $img);
$data = base64_decode($img);
$file = UPLOAD_DIR . uniqid() . '.jpg';
$success = file_put_contents($file, $data);
$fullURL = $file;
$val = media_sideload_image($fullURL, $post_id, 'none');
echo $val;

上面的示例不会删除旧的临时文件,但您可以很容易地找到如何删除。我觉得这个解决方案简单得多,效果也很好。

我将更新这篇文章,告诉大家我是如何做的,以防其他人正在努力将画布数据保存到Wordpress作为文章附件

我使用了media\u sideload\u image函数,而不是使用media\u handle\u upload,您必须使用$\u FILES数组。为了做到这一点,您只需将画布图像保存到服务器上的一个文件夹中,然后将该URL传递给media_sideload_image和post ID即可。它会将该文件附加到您的帖子中,并将图像复制到您的上载文件夹中。您可以在服务器上创建TEMP_UPLOADS文件夹来存储上载的文件,然后在成功将其附加到帖子后手动删除

define('UPLOAD_DIR', 'path/to/termp-folder/');
$img = $_POST['img'];
$post_id = $_POST['postId'];
$post_id = (int) $post_id;
$img = str_replace('data:image/jpeg;base64,', '', $img);
$img = str_replace(' ', '+', $img);
$data = base64_decode($img);
$file = UPLOAD_DIR . uniqid() . '.jpg';
$success = file_put_contents($file, $data);
$fullURL = $file;
$val = media_sideload_image($fullURL, $post_id, 'none');
echo $val;

上面的示例不会删除旧的临时文件,但您可以很容易地找到如何删除。我觉得这个解决方案简单得多,效果也很好。

你能把数据放在某个地方,然后制作你自己的人造文件数组来欺骗函数吗。。。刚刚尝试过,但它与is_uploaded_file()相冲突,后者检查$_FILES['whateverfile']['tmp_name']是否确实是通过HTTP POST上载的,当然它不再是HTTP POST,因为它现在指向一个新文件:(无论如何,谢谢你的回复,好的先生!实际上我还想到了另一种方法——让ajax请求看起来像是从标准表单生成的请求(实际上是有效的).我想我会为这个问题提出另一个问题,因为这是一个稍微不同的主题。再次感谢!嗯…这不起作用,但我刚刚设法让你的原始建议生效!我会编辑原始问题,并将代码放入,以利其他任何挣扎的人