我知道我可以很容易地用 CURL 做到这一点,但我想知道是否可以使用
file_get_contents()
和 http 流上下文来将文件上传到远程 Web 服务器,如果可以,怎么做?
首先,
multipart
Content-Type的第一条规则是定义一个边界,作为每个部分之间的分隔符(因为顾名思义,它可以有多个部分)。边界可以是内容正文中未包含的任何字符串。我通常会使用时间戳:
define('MULTIPART_BOUNDARY', '--------------------------'.microtime(true));
定义边界后,您必须将其与
Content-Type
标头一起发送,以告诉网络服务器期望的分隔符:
$header = 'Content-Type: multipart/form-data; boundary='.MULTIPART_BOUNDARY;
完成后,您必须构建一个与 HTTP 规范和您发送的标头相匹配的适当内容主体。如您所知,从表单发布文件时,您通常会有一个表单字段名称。我们将定义它:
// 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";
如您所见,我们发送带有
Content-Disposition
处置的 form-data
标头,以及 name
参数(表单字段名称)和 filename
参数(原始文件名)。如果您想正确填充Content-Type
thingy.,发送具有正确MIME类型的
$_FILES[]['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 可以很好地处理二进制文件。
或者也许你可以这样做:
$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”更改为适当的路径