使用file_get_contents上传文件

Sha*_*obe 33 php file-upload file-get-contents

我意识到我可以很容易地用CURL做到这一点,但我想知道是否可以使用file_get_contents()http流上下文将文件上传到远程Web服务器,如果是的话,怎么样?

net*_*der 82

首先,multipartContent-Type 的第一个规则是定义一个边界,该边界将用作每个部分之间的分隔符(因为顾名思义,它可以有多个部分).边界可以是内容体中未包含的任何字符串.我通常会使用时间戳:

define('MULTIPART_BOUNDARY', '--------------------------'.microtime(true));
Run Code Online (Sandbox Code Playgroud)

定义边界后,必须使用Content-Type标头发送它以告诉Web服务器期望的分隔符:

$header = 'Content-Type: multipart/form-data; boundary='.MULTIPART_BOUNDARY;
Run Code Online (Sandbox Code Playgroud)

完成后,您必须构建一个与HTTP规范和您发送的标头匹配的正确内容主体.如您所知,在从表单发布文件时,通常会有一个表单字段名称.我们将定义它:

// equivalent to <input type="file" name="uploaded_file"/>
define('FORM_FIELD', 'uploaded_file'); 
Run Code Online (Sandbox Code Playgroud)

然后我们构建内容体:

$filename = "/path/to/uploaded/file.zip";
$file_contents = file_get_contents($filename);    

$content =  "--".MULTIPART_BOUNDARY."\r\n".
            "Content-Disposition: form-data; name=\"".FORM_FIELD."\"; filename=\"".basename($filename)."\"\r\n".
            "Content-Type: application/zip\r\n\r\n".
            $file_contents."\r\n";

// add some POST fields to the request too: $_POST['foo'] = 'bar'
$content .= "--".MULTIPART_BOUNDARY."\r\n".
            "Content-Disposition: form-data; name=\"foo\"\r\n\r\n".
            "bar\r\n";

// signal end of request (note the trailing "--")
$content .= "--".MULTIPART_BOUNDARY."--\r\n";
Run Code Online (Sandbox Code Playgroud)

如您所见,我们发送Content-Disposition带有form-data处置的标题,以及name参数(表单字段名称)和filename参数(原始文件名).Content-Type如果要正确填充$_FILES[]['type']thingy ,使用正确的MIME类型发送标头也很重要.

如果您要上传多个文件,只需使用$ content位重复该过程,当然,FORM_FIELD每个文件都有不同的内容.

现在,构建上下文:

$context = stream_context_create(array(
    'http' => array(
          'method' => 'POST',
          'header' => $header,
          'content' => $content,
    )
));
Run Code Online (Sandbox Code Playgroud)

并执行:

file_get_contents('http://url/to/upload/handler', false, $context);
Run Code Online (Sandbox Code Playgroud)

注意:在发送二进制文件之前无需对其进行编码.HTTP可以很好地处理二进制文件.

  • 那效果很好。您是否还有机会在答案中添加如何在上传时添加额外的帖子字段?另外,是否可以通过添加另一个边界来以这种方式进行多次操作? (2认同)
  • 如果要发送的文件很大,有没有办法发送大块数据怎么办? (2认同)