PUT raw data comes in php://input, and you have to use fopen() and fread() to get the content. file_get_contents() is useless.
The HTTP PUT request MUST contain a Content-Length header to specify the length (in bytes) of the body, or the server will not be able to know when the input stream is over. This is the common problem for many to find the php://input empty if no such header available.
This should make PUT work properly on win32 using PHP5.1.1 and apache2.
PUT 방식 지원
PUT 방식 지원은 PHP 3와 PHP 4에서 차이가 있습니다. PHP 4에서는, 표준 입력 스트림으로 HTTP PUT의 내용을 읽어야 합니다.
Example#1 PHP 4로 HTTP PUT 파일을 저장하기
<?php
/* PUT 데이터는 stdin 스트림으로 들어옵니다. */
$putdata = fopen("php://stdin", "r");
/* 쓰기 위한 파일을 엽니다. */
$fp = fopen("myputfile.ext", "w");
/* 한번에 1kb씩 읽어서 파일에 씁니다. */
while ($data = fread($putdata, 1024))
fwrite($fp, $data);
/* 스트림을 닫습니다. */
fclose($fp);
fclose($putdata);
?>
Note: 아래의 문서는 PHP 3에만 해당합니다.
PHP는 Netscape Composer나 W3C Amaya 등의 클라이언트에서 사용하는 HTTP PUT 방식에 대한 지원을 제공합니다. PUT 요청은 파일 업로드보다 단순하고 다음과 같은 식으로 이루어집니다.
PUT /path/filename.html HTTP/1.1
일반적으로 원격 클라이언트가 웹 트리의 /path/filename.html에 내용을 저장하는걸 의미합니다. 아파치나 PHP가 웹 트리의 모든 파일에 누구나 자동적으로 덮어쓰게 하는 것은 좋은 생각이 아닙니다. 그래서, 웹 서버에 이러한 요청이 들어왔을때, PHP 스크립트를 통해서 다루도록 할 수 있습니다. 아파치에서는 Script 지시자를 통해 지정할 수 있습니다. 아파치 환경 설정 파일의 거의 모든 곳에서 지정할 수 있습니다. 일반적으로는 <Directory> 블록이나 <Virtualhost> 블록의 내부에 위치하게 됩니다. 다음 줄을 추가하면 됩니다:
Script PUT /put.php
이는 아파치가 이 줄이 들어가 있는 URI에 해당하는 모든 PUT 요청을 put.php 스크립트에 전달하게 합니다. 물론, .php 확장자에 대해 PHP가 사용 가능한 상태여야 합니다.
put.php 파일 안에서는 다음과 같은 작업을 해야 합니다:
<?php copy($PHP_UPLOADED_FILE_NAME, $DOCUMENT_ROOT . $REQUEST_URI); ?>
파일을 원격 클라이언트에서 요청한 위치로 복사합니다. 파일 복사가 이루어지기 전에 몇가지 체크나 사용자 인증을 할 수 있습니다. 여기서 보였듯이 PHP는 PUT 방식 요청을 POST 방식을 다루는 것과 마찬가지로 임시 파일로 저장합니다. 요청이 끝날 때, 임시 파일은 삭제됩니다. 그러므로, PUT을 다루는 PHP 스크립트는 파일을 어딘가로 복사해야합니다. 임시 파일의 파일명은 $PHP_PUT_FILENAME 변수에 들어있고, 대상 파일명의 지정은 $REQUEST_URI에서 확인할 수 있습니다. (아파치가 아닌 경우 다를 수 있습니다) 대상 파일 이름은 원격 클라이언트가 지정합니다. 이 클라이언트로부터의 지정을 무시할 수 있습니다. 예를 들면, 모든 전송 파일을 특별한 업로드 디렉토리로 복사할 수 있습니다.
PUT 방식 지원
14-Dec-2005 04:01
20-Sep-2005 02:11
Here's my solution on my Note below
The .htacces-File
Options FollowSymLinks
RewriteEngine on
RewriteBase !!!The Path of your PUT-Upload-Folder, relative to the DocumentRoot!!!
RewriteRule ^index\.php$ - [L]
RewriteRule ^(.*)$ index.php?url=$1 [L]
index.php:
<?php
if ($_SERVER['REQUEST_METHOD'] == "PUT")
{ $f = fopen(basename($_SERVER['REQUEST_URI']), "w");
$s = fopen("php://input", "r");
while($kb = fread($s, 1024))
{ fwrite($f, $kb, 1024); }
fclose($f);
fclose($s);
Header("HTTP/1.1 201 Created"); }
elseif ($_SERVER['REQUEST_METHOD'] == "GET")
{ readfile(basename($_SERVER['REQUEST_URI'])); }
?>
Testes with Apache 2 and PHP 5, php as a module (win32)
20-Sep-2005 01:22
NOTE: The <Script>-Directive can not be placed in .htaccess files.
So if you're having shared webspace and no access to the apache-configuration file you will have little chance to make something like this work.
But you can solve the problem, using mod_rewrite (for Apache) - for further information see the documentation at http://httpd.apache.org/docs/2.0/mod/mod_rewrite.html
15-Aug-2005 02:16
A Case Study: To set up publishing with Netscape 7.2 Composer to Apache/PHP, no need to use CGI (which I tried unsuccessfully for too long) or to alter Apache's httpd.conf. I needed only to click Publish As, fill in put2disk.php as the filename (where its contents are the below), and fill in that file's dir as the "Publishing address".
XAMPP 1.4.14: Apache/2.0.54 (Win32) mod_ssl/2.0.54 OpenSSL/0.9.7g PHP/5.0.4.
<? // filename: put2disk.php.
//file_put_contents ("get_def.out", print_r (get_defined_vars(), TRUE)); // debugging
// Two slurp methods: (a) didn't work, (b) did.
//$stdin_rsc = fopen("php://input", "r");
//$putdata='';
//while ($putdata .= fread($stdin_rsc, 1024)); // a. Hangs the "Publishing..." dialog.
//while (!feof($stdin_rsc)) $putdata.=fread($stdin_rsc, 8192); // b. Worked, but file_get_contents is faster.
//fclose($stdin_rsc);
// All that's nec:
$putdata=file_get_contents('php://input'); // Not php://stdin! (When the ability to see error messages isn't available, the doc (this manual page) needs to be more accurate.)
file_put_contents("stdin.out",$putdata);
?>
18-Apr-2004 12:59
Trying to capture a PUT stream into a single variable seems not to be allowed, probably because of the non presence of some kind of EOF. In this way save a PUT request into a database isn't easy.
The only way I find would be output to a cache file, then either insert filename into db or read again its content and place it in some kind of query.
03-Nov-2003 02:41
I have spent a lot of time trying to make PUT work with Apache 2.0.40. I have not yet been able to find any way of making the Script directive invoke php via mod_php, the only way has been to have a file called example.cgi and invoke it via CGI, with the file starting
#!/usr/bin/php
so the PHP interpreter is invoked through the CGI mechanism and not as a module.
If there IS a way of making it work 'right' I'd love to know! After six hours of messing around, I've settled for CGI. The error messages in the apache error log are significantly misleading and the whole thing has been an exercise in frustration.
Attempts to use AddHandler and all 'normal' ways of trying to persuade Apache to do this have been fruitless. It does seem as if PUT can only be handled by CGI invocation.
13-Feb-2003 10:21
I can only make it work when I am using PHP as CGI, not as an Apache module.
I am using the version of PHP/Apahce that is shipped with Debian/testing.
You have to load the action_module, but not the put_module in Apache config.
