2010-10-23 43 views
28

Tôi nhận ra mình có thể làm điều này với CURL rất dễ dàng, nhưng tôi đã tự hỏi liệu có thể sử dụng file_get_contents() với ngữ cảnh luồng http để tải tệp lên máy chủ web từ xa hay không ?Tải lên tệp bằng cách sử dụng file_get_contents

+1

Bạn không có nghĩa là file_put_contents()? – mellowsoon

+0

Không. Hãy thử làm file_put_contents với một URL và bạn sẽ nhận được "HTTP wrapper không hỗ trợ các kết nối có thể ghi" – Shabbyrobe

+1

Nhưng với * file_get_contents() * bạn có thể tải các tập tin, không tải lên !? – KingCrunch

Trả lời

69

Trước hết, nguyên tắc đầu tiên của multipart Content-Type là xác định một ranh giới sẽ được sử dụng như một dấu phân cách giữa mỗi phần (vì như tên gọi của mình, nó có thể có nhiều phần). Ranh giới có thể là bất kỳ chuỗi nào không có trong nội dung. Tôi thường sẽ sử dụng một dấu thời gian:

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

Khi ranh giới của bạn được định nghĩa, bạn phải gửi nó với Content-Type tiêu đề để nói với webserver gì delimiter mong đợi:

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

Khi đã xong, bạn phải xây dựng một nội dung phù hợp phù hợp với đặc tả HTTP và tiêu đề bạn đã gửi. Như bạn đã biết, khi POST một tệp từ một biểu mẫu, bạn thường sẽ có một tên trường biểu mẫu. Chúng tôi sẽ xác định nó:

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

Sau đó, chúng tôi xây dựng cơ thể nội dung:

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

Như bạn có thể thấy, chúng tôi đang gửi header Content-Disposition với form-data bố trí, cùng với thông số name (tên trường biểu mẫu) và thông số filename (tên tệp gốc). Điều quan trọng là gửi tiêu đề Content-Type với loại MIME thích hợp, nếu bạn muốn điền chính xác điều khoản $_FILES[]['type'].

Nếu bạn có nhiều tệp để tải lên, bạn chỉ cần lặp lại quy trình với bit $ nội dung, với tất nhiên, một FORM_FIELD khác nhau cho mỗi tệp.

Bây giờ, xây dựng bối cảnh:

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

Và thực hiện:

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

LƯU Ý: Không cần để mã hóa tập tin nhị phân của bạn trước khi gửi đi. HTTP có thể xử lý nhị phân tốt.

+0

Câu trả lời tuyệt vời, tuyệt vời. Sẽ cố gắng này ra tối nay. – Shabbyrobe

+1

Điều đó có hiệu quả. Có cơ hội nào bạn cũng có thể thêm vào câu trả lời của bạn làm thế nào để thêm các trường đăng thêm với tải lên? Ngoài ra, có thể thực hiện nhiều theo cách này chỉ bằng cách tacking trên một ranh giới khác không? – Shabbyrobe

+0

Chắc chắn. Đối với các trường POST, hãy xem câu trả lời cập nhật của tôi. Đối với câu hỏi thứ hai của bạn, tôi không chắc chắn những gì bạn có ý nghĩa. – netcoder

0

Bạn có thể gửi yêu cầu POST với tiêu đề Content-Type: multipart/form-data và mã hóa tệp của mình theo cách thủ công là multipart/form-data.

file_get_contents(URL, false, stream_context_create(array(
    'http' => array(
     'method' => 'POST', 
     'headers' => 'Content-Type: multipart/form-data' 
     'content' => MULTIPART_ENCODED_FILE, 
    ), 
))); 
+0

Tôi làm cách nào để mã hóa tệp? – Shabbyrobe

+0

@Shabbyrobe: Vâng, đó là chính xác câu hỏi ... Tôi không biết làm thế nào mã hóa multipart hoạt động, vì vậy không thể giúp bạn ở đó. – NikiC

+1

Thử 'base64_encode()', http://php.net/manual/en/function.base64-encode.php. –

Các vấn đề liên quan