php:// stdin读取额外的字符

时间:2015-05-30 22:38:49

标签: javascript php jquery http-put

我正在制作一个系统的奇怪问题。我正在尝试创建一个将文件上传到服务器的系统。我没有直接文件写入权限,HTTP POST multipart/form-data文件上传不起作用。遗憾的是,我无法直接访问服务器。

我的解决方案是使用jQuery的$.ajax函数通过HTTP PUT上传文件,然后从服务器上的PHP中的STDIN读取它,并通过FTP将内容上传到其他位置。

一切似乎都有效,但是在某个地方,正在添加额外的字节。在客户端,Windows声称该文件(我使用我的网站的favicon.ico文件测试)是7358字节。一旦我使用标准的Javascript FileReader对象读入文件,它似乎只有7311字节。然后,我成功将它PUT到服务器上的PHP脚本,声称它读取10890字节,当我通过FTP检查转储文件夹时,FileZilla同意。

以下是我要上传的Javascript代码(包含jQuery 1.11.3,file_input<input type="file" id="file_input"/>

function upload(){
console.log("upload");
var f = file_input.files[0];
var r = new FileReader();
r.onload = function(event){
    var d = r.result;
    console.log("data loaded");
    console.log(d.length);
    $.ajax({
        url: "upload.php?name="+encodeURIComponent(f.name)+"&mime="+encodeURIComponent(f.mime),
        context: document.body,
        method: "PUT",
        contentType: "application/octet-stream",
        data: d
        }).done(function(data){
            console.log("done");
            console.log(data);
            });
};
r.onerror = function(event){
    alert("ERROR READING FILE!\nCode " + event.target.error.code);
};
r.readAsText(f);
console.log("initiated");
}

如您所见,名称和MIME类型通过GET查询字符串包含。

这是我的PHP接受上传(upload.php的一部分):

if(strtoupper($_SERVER['REQUEST_METHOD'])=="PUT"){
    echo "uploading\n";
    echo "connected\n";
    var_dump($_POST);
    echo "x";
    $file=fopen("php://input","r");
    var_dump($file);
    $x="";
    while($byte=fgetc($file)!==false){
        $x.=$byte;
    }
    echo strlen($x);
    echo "\n";
    $ftp=fopen('ftp://user:pass@example.com/admin/fs/upload/'.uniqid('',true),'w');
    var_dump($ftp);
    fwrite($ftp,$x);
    fclose($ftp);
    echo "done\n";
}

我检查了记事本中的文件,并且大部分文件似乎没有变化(没有任何HTTP标头或任何内容),但新文件拒绝在任何图像查看器中打开(原始文件)。基于文件的差异 - 只有一些部分是变化,并且它们被改为看似随机的非可视字符 - 我猜它与字符编码差异有关。任何想法都将不胜感激。

谢谢,

MagikM18

修改

我的服务器是Apache / 2.4.6并在x86_64-redhat-linux-gnu上运行(根据phpinfo())。

另外,我使用基于文本的文件(PHP脚本)对其进行了测试,它运行得很好 - 它必须与文件的二进制内容有关。

1 个答案:

答案 0 :(得分:0)

对于二进制文件(即不是文本),您可以尝试将b附加到fopen的标记:

fopen("php://input","rb");
/*
...
*/
$ftp=fopen('ftp://user:pass@example.com/admin/fs/upload/'.uniqid('',true),'wb');

修改

除了接收流之外,您还必须以二进制形式发送文件。请参阅评论中的链接。