Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
147 views
in Technique[技术] by (71.8m points)

php - Upload a file using file_get_contents

I realise I can do this with CURL very easily, but I was wondering if it was possible to use file_get_contents() with the http stream context to upload a file to a remote web server, and if so, how?

Question&Answers:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

First of all, the first rule of multipart Content-Type is to define a boundary that will be used as a delimiter between each part (because as the name says, it can have multiple parts). The boundary can be any string that is not contained in the content body. I will usually use a timestamp:

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

Once your boundary is defined, you must send it with the Content-Type header to tell the webserver what delimiter to expect:

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

Once that is done, you must build a proper content body that matches the HTTP specification and the header you sent. As you know, when POSTing a file from a form, you will usually have a form field name. We'll define it:

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

Then we build the content body:

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

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

".
            $file_contents."
";

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

".
            "bar
";

// signal end of request (note the trailing "--")
$content .= "--".MULTIPART_BOUNDARY."--
";

As you can see, we're sending the Content-Disposition header with the form-data disposition, along with the name parameter (the form field name) and the filename parameter (the original filename). It is also important to send the Content-Type header with the proper MIME type, if you want to correctly populate the $_FILES[]['type'] thingy.

If you had multiple files to upload, you just repeat the process with the $content bit, with of course, a different FORM_FIELD for each file.

Now, build the context:

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

And execute:

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

NOTE: There is no need to encode your binary file before sending it. HTTP can handle binary just fine.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...