【问题标题】:Upload a file using file_get_contents使用 file_get_contents 上传文件
【发布时间】:2011-04-29 13:45:52
【问题描述】:

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

【问题讨论】:

  • 你不是说file_put_contents()吗?
  • 不。尝试使用 URL 执行 file_put_contents,你会得到“HTTP wrapper does not support writeable connections”
  • 但是使用 file_get_contents() 你可以下载文件,而不是上传!?
  • 如何使用 file_get_contents()write 到流中? :?
  • 实际上,HTTP 流包装器总是写入流,因为 HTTP 调用同时包含请求(写入)和响应(读取)。

标签: php file-upload file-get-contents


【解决方案1】:

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

define('MULTIPART_BOUNDARY', '--------------------------'.microtime(true));

一旦定义了边界,您必须将其与Content-Type 标头一起发送,以告知网络服务器期望的分隔符:

$header = 'Content-Type: multipart/form-data; boundary='.MULTIPART_BOUNDARY;

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

// equivalent to <input type="file" name="uploaded_file"/>
define('FORM_FIELD', 'uploaded_file'); 

然后我们构建内容体:

$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";

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

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

现在,构建上下文:

$context = stream_context_create(array(
    'http' => array(
          'method' => 'POST',
          'header' => $header,
          'content' => $content,
    )
));

并执行:

file_get_contents('http://url/to/upload/handler', false, $context);

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

【讨论】:

  • 哇,很棒的答案。今晚会试试这个。
  • 效果很好。您是否有机会在您的答案中添加如何在上传时添加额外的帖子字段?另外,是否可以通过在另一个边界上进行多次这样的操作?
  • 当然。对于 POST 字段,请参阅我更新的答案。至于你的第二个问题,我不确定你的意思。
  • 感谢您的更新。我的意思是我可以通过添加另一个文件一次上传两个文件:$content = "--".MULTIPART_BOUNDARY."\r\n"。 “内容处置:表单数据;名称=\”form_field_2\”;文件名=\”“.basename($otherFileName)。”\“\r\n”。 “内容类型:图像/jpeg\r\n\r\n”。 $otherFileContents."\r\n";
  • 如果你要发送的文件很大,有没有办法发送大块数据?
【解决方案2】:

或者你可以这样做:

$postdata = http_build_query(
array(
    'var1' => 'some content',
    'file' => file_get_contents('path/to/file')
)
);

$opts = array('http' =>
    array(
        'method'  => 'POST',
        'header'  => 'Content-Type: application/x-www-form-urlencoded',
        'content' => $postdata
    )
);

$context  = stream_context_create($opts);
$result = file_get_contents('http://example.com/submit.php', false, $context);

您需要将“/path/to/file”更改为适当的路径

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-03-08
    • 1970-01-01
    • 1970-01-01
    • 2019-04-30
    • 1970-01-01
    相关资源
    最近更新 更多