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.
Supporto per metodo PUT
Il supporto al metodo PUT è cambiato tra PHP 3 e PHP 4. In PHP 4 occorre utilizzare il flusso standard di input per leggere il contenuto di un PUT HTTP.
Example #1 Salvataggio di un file HTTP PUT con PHP 4
<?php
/* I dati PUT arrivano in stdin */
$putdata = fopen("php://stdin", "r");
/* Apertura del file in scrittura */
$fp = fopen("myputfile.ext", "w");
/* Lettura dei dati d 1kb alla volta e scrittura nel file */
while ($data = fread($putdata, 1024))
fwrite($fp, $data);
/* Chiusura */
fclose($fp);
fclose($putdata);
?>
Nota: Tutta la documentazione che segue si applica solo a PHP 3.
PHP fornisce supporto per il metodo HTTP PUT utilizzato da programmi come Netscape Composer e W3C Amaya. Le richieste PUT sono molto più semplici rispetto al caricamento di un file, e assomigliano a
PUT /percorso/nomefile.html HTTP/1.1
Questo significa che normalmente il programma remoto intende salvare il contenuto della richesta come : /path/filename.html nel filesystem sul server web. Non è ovviamente una buona idea per Apache o PHP lasciare a un qualsiasi utente la possibilità di sovrascrivere file sul server web. Quindi, per gestire questa richiesta si deve chiedere al server web che si vuole che sia un certo script PHP a gestire la richiesta stessa. In Apache si ottiene questo con la direttiva Script. Può essere posta quasi ovunque nel file di configurazione di Apache. Un posto frequente è all'interno di un blocco <Directory> oppurte all'interno del blocco <Virtualhost>. Un linea come la seguente è sufficiente:
Script PUT /put.php
Questo chiede ad Apache di inviare tutte le richieste PUT che soddisfano il contesto in cui si è inserito questo comando allo script put.php. Questo richiede, naturalmente, che sia abilitato PHP per l'estensione .php e che PHP sia attivo.
All'interno del file put.php si può inserire qualcosa del tipo:
<?php copy($PHP_UPLOADED_FILE_NAME, $DOCUMENT_ROOT . $REQUEST_URI); ?>
Questo copia il file nella posizione chiesta dal programma remoto. E' probabile che si vogliano effettuare dei controlli o autenticazioni dell'utente prima di effettuare questa copia. L'unica magia qui presente è che quando PHP vede una richiesta con metodo PUT memorizza il file caricato in un file temporaneo così come per i file caricati con il metodo POST. Quando la richiesta termina, questo file temporaneo è eliminato. Quindi il gestore della richiesta PUT deve copiare il file da qualche parte. Il nome del file temporaneo è memorizzato nella variabile $PHP_PUT_FILENAME, ed è possibile vedere il nome del file di destinazione nella variabile $REQUEST_URI (potrebbe variare su web server diversi da Apache). Qusto nome di file di destinazione è quello specificato dal client remoto. Non è necessario seguire le indicazioni del client. E' possibile, per esempio, copiare tutti i file caricati in una apposita directory.
Supporto per metodo 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.
