使用file_get_contents上传文件

2022-08-30 10:52:57

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


答案 1

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

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

定义边界后,必须将其与标头一起发送,以告知 Web 服务器预期的分隔符:Content-Type

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

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

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

如您所见,我们将标头与处置一起发送,以及参数(表单字段名称)和参数(原始文件名)。如果要正确填充内容,则使用正确的MIME类型发送标头也很重要。Content-Dispositionform-datanamefilenameContent-Type$_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可以很好地处理二进制文件。


答案 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”更改为适当的路径


推荐