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 methode ondersteuning
De PUT methode ondersteuning is sterk veranderd tussen PHP 3 en PHP 4 In PHP 4, wordt aangeraden om mbv de standaard input stream de inhoud van de HTTP PUT te lezen.
Example#1 Opslaan van HTTP PUT bestanden met PHP 4
<?php
/* PUT data komt binnen via de stdin stream */
$putdata = fopen("php://stdin","r");
/* Open een bestand om naar te schrijven */
$fp = fopen("myputfile.ext","w");
/* Lees de data 1kb per keer, en schrijf
deze daarna weg */
while ($data = fread($putdata,1024))
fwrite($fp,$data);
/* Sluit alles af */
fclose($fp);
fclose($putdata);
?>
Note: De uitleg hieronder geld alleen voor PHP 3.
PHP ondersteunt ook de HTTP PUT methode welke gebruikt wordt door o.a. Netscape Composer en W3C Amaya. PUT aanvragen zijn veel simpeler dan een bestand uploaden en zien er ongeveer als volgt uit:
PUT /pad/bestandsnaam.html HTTP/1.1
Dit betekent normaal gezien dat de server het bestand ook als /pad/filename.html wilt opslaan. Dit is natuurlijk geen goed idee omdat je niet wilt dat anderen bestanden overschrijven in je web tree. Om zo'n 'request' te verwerken vertel je je server eerst met wat voor PHP script je dit request wilt verwerken. Met Apache kun je dit doen met het Script directive. Het kan ongeveer overal in je configuratie bestand geplaatst worden. Een standaard plaats hiervoor is bijvoorbeeld een <Directory> blok. Een enkele regel als voorbeeld:
Script PUT /put.php
Dit vertelt Apache om alle PUT requests waarvoor URIs die overeenkomen met de context waarin deze regel geplaatst is, naar het put.php script te sturen. We gaan er vanuit dat je de juist mime-headers heb gebruikt om PHP met de .php extensie te laten werken en dat PHP actief is.
In je 'put.php' zou je dan iets als volgt neer zetten:
<?php copy($PHP_UPLOADED_FILE_NAME,$DOCUMENT_ROOT.$REQUEST_URI); ?>
Dit kopieert het bestand naar de locatie welke gevraagd werd in het request. Waarschijnlijk zal je nog enige tests uitvoeren op het bestand voordat je het bestand daadwerkelijk kopieert. De enige truc hier is dat PHP het bestand opslaat in een tijdelijk bestand zoals bij de POST-methode. Zogauw het request is afgehandeld word het tijdelijke bestand verwijderd. Let dus op dat je script het tijdelijke bestand verplaatst of hernoemd. De naam van dit tijdelijke bestand is opgeslagen in de variable $PHP_PUT_FILENAME en je kunt de voorgestelde locatie vinden in $REQUEST_URI (Dit kan anders zijn bij niet-Apache web servers). Dit is nogmaals een suggestie van de gebruiker. Je hoeft deze suggestie niet te gebruiken, je kunt bijvoorbeeld alle bestanden in een speciale uploads directory plaatsen.
PUT methode ondersteuning
14-Dec-2005 01:01
20-Sep-2005 11: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 10: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 11: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 09: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 11: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 07: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.
