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.
Soporte del método PUT
PHP soporta el metodo HTTP PUT que usan aplicaciones como Netscape Composer y Amaya del W3C. Las peticiones PUT son más sencillas que el método POST. Un ejemplo:
PUT /path/filename.html HTTP/1.1
Esto normalmente significaría que el cliente remoto quiere salvar el contenido como: /path/filename.html en tu árbol web. Lógicamente no una buena idea que la gente pueda escribir en tu árbol web. Para manipular esta petición debes decirle al servidor que esta petición sea atendida por un script PHP. En Apache, por ejemplo, se utiliza para esto la directiva Script en los alguno de los archivos de configuración del servidor. Un sitio típico de uso es dentro del bloque <Directory> o quizás en el bloque <Virtualhost>. Una linia así deberia hacer ésta función:
Script PUT /put.php
Ésto le dice a Apache que envíe todas peticiones PUT para URIs que contengan esta linia al script put.php. Se asume que PHP se encuentra activo y con la extensión .php enlazada a él.
Dentro del script put.php3 se podría implementar algo así:
<?php copy($PHP_UPLOADED_FILE_NAME,$DOCUMENT_ROOT.$REQUEST_URI); ?>
Esto copiaría el archivo a la localización requerida por el cliente remoto. Aqui se pueden ejecutar funciones de autentificación de usuario o cualquier otro tipo de chequeo. El archivo se guarda en el archivo temporal del sistema servidor de la misma manera que el Método POST. Cuando la petición finaliza, el archivo temporal es eliminado. En consequencia el script dede proceder al trato de éste inmediatamente, ya sea para copiarlo, renombrarlo, etc. El archivo se encuentra en la variable $PHP_PUT_FILENAME, y el destino sugerido por el cliente en la variable $REQUEST_URI (puede variar en servidores web que no sean Apache). No es necesario hacer caso al destino sugerido por el cliente. Por ejemplo se podrían copiar los archivos enviados a directorios especialmente designados para esta tarea.
Soporte del método PUT
14-Dec-2005 08:01
21-Sep-2005 05: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)
21-Sep-2005 04: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 05: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);
?>
19-Apr-2004 03: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.
04-Nov-2003 06: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.
14-Feb-2003 02: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.
