【问题标题】:$HTTP_RAW_POST_DATA and Wordpress media_handle_upload$HTTP_RAW_POST_DATA 和 Wordpress media_handle_upload
【发布时间】:2011-03-12 16:09:17
【问题描述】:

所以我正在制作一些用户需要使用 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);
...
?>

问题是,Wordpress 的 media_handle_upload() 只接受 $_FILES 数组的索引以进行上传。

所以问题是:如何将图像数据从 HTTP_RAW_POST_DATA 传递给它?我可以让 $_FILES['tmp-name'] 以某种方式指向它吗?我可以以某种方式使用另一个脚本作为中间步骤吗?我可以在打字机上释放猴子直到他们想出答案吗?

非常感谢任何帮助!

谢谢, 凯恩

编辑:已解决

感谢 @alex 的 file_put_contents 建议,并回答了我发布的另一个相关问题 here 我现在可以正常工作了。解决方案:在 HTTP 请求中发送未更改的 base64 图像数据,覆盖 PHP 生成的 tmp_file 并为 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 );

?>

【问题讨论】:

  • 你能不能 file_put_contents() 某个地方的数据,然后制作你自己的假 $_FILES 数组来欺骗函数?
  • Hmm... 刚刚尝试过,但它违反了 is_uploaded_file() 检查 $_FILES['whateverfile']['tmp_name'] 是否实际上是通过 HTTP POST 上传的,当然它是'不再是因为它现在指向一个新文件:(谢谢你的回复,好先生!
  • 实际上我想到了另一种方法 - 使 ajax 请求看起来像从标准表单生成的请求(实际上有效)。想我会为那个问题提出另一个问题,因为它是一个稍微不同的话题。再次感谢!
  • 嗯...这没有用,但我刚刚设法得到你原来的建议!我将编辑原始问题并将代码放入其中,以帮助其他为此苦苦挣扎的人:)
  • 我会发表我的评论作为答案:)

标签: php ajax wordpress file-upload canvas


【解决方案1】:

您可以在某处 file_put_contents() 数据,然后制作自己的虚假 $_FILES 数组来欺骗 WordPress 功能。

【讨论】:

    【解决方案2】:

    我将用我的做法来更新这篇文章,以防其他人正在努力将 Canvas 数据作为帖子附件保存到 Wordpress。

    我使用了 media_sideload_image 函数,而不是必须使用 $_FILES 数组的 media_handle_upload。为此,您只需将画布图像保存到服务器上的文件夹中,然后将该 URL 传递给 media_sideload_image 和帖子 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;
    

    上面的示例不会删除旧的临时文件,但您可以很容易地弄清楚如何做到这一点。我觉得这个解决方案要简单得多,而且效果很好。

    【讨论】:

      猜你喜欢
      • 2016-12-25
      • 2013-03-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-12-28
      • 2014-12-03
      相关资源
      最近更新 更多