PUT-Unterstützung
PHP unterstützt die HTTP-PUT-Methode, welche von einigen Clients verwendet
wird, um Dateien auf dem Server zu speichern. PUT-Anfragen sind weitaus
unkomplizierter als ein POST-Dateiupload und sehen etwa so aus:
Das würde normalerweise bedeuten, dass der Client den nachfolgenden Inhalt
als /path/filename.html auf dem Server speichern
will. Natürlich ist es keine gute Idee, dass PHP oder Apache jeden
Benutzer beliebige Dateien überschreiben lässt. Um eine solche Anfrage
bearbeiten zu können, muss der Webserver erst angewiesen werden, ein
bestimmtes PHP-Skript für die Abarbeitung aufzurufen. In Apache wird dies
durch die Direktive Script festgelegt. Sie kann fast
überall in der Apache-Konfigurationsdatei platziert werden, gebräuchlich
ist die Platzierung innerhalb eines <Directory>
-
oder Virtualhost
-Abschnitts. Eine Zeile wie die
folgende erledigt dies:
Diese Zeile legt fest, dass Apache alle PUT-Anfragen für URIs, die dem
Kontext entsprechen, in dem diese Zeile steht, an das
put.php Skript weiterleitet. Dies setzt natürlich
voraus, dass PHP aktiv und für die
.php-Dateierweiterung registriert
ist.
In der put.php könnte anschließend ein Code wie der folgende verwendet
werden. Dieser würde den Inhalt der hochgeladenen Datei in die Datei
myputfile.ext auf dem Server kopieren.
Beispiel #1 Speichern von HTTP-PUT-Dateien
<?php
/* PUT Daten kommen in den stdin Stream */
$putdata = fopen("php://input","r");
/* Eine Datei zum Schreiben öffnen */
$fp = fopen("myputfile.ext","w");
/* Jeweils 1kB Daten lesen und
in die Datei schreiben */
while ($data = fread($putdata,1024))
fwrite($fp,$data);
/* Die Streams schließen */
fclose($fp);
fclose($putdata);
?>
micronix at gmx dot net ¶14 years ago
Hello PHP World After many Hours of worryness :=)
I have found the Solution for Resume or Pause Uploads
In this Code Snippet it is the Server Side not Client on any Desktop Programm you must use byte ranges to calculate the uploaded bytes and missing of total bytes.
Here the PHP Code
<?php
$CHUNK = 8192;
try {
if (!($putData = fopen("php://input", "r")))
throw new Exception("Can't get PUT data.");
$tot_write = 0;
$tmpFileName = "/var/dev/tmp/PUT_FILE";
if (!is_file($tmpFileName)) {
fclose(fopen($tmpFileName, "x")); if (!($fp = fopen($tmpFileName, "w")))
throw new Exception("Can't write to tmp file");
while ($data = fread($putData, $CHUNK)) {
$chunk_read = strlen($data);
if (($block_write = fwrite($fp, $data)) != $chunk_read)
throw new Exception("Can't write more to tmp file");
$tot_write += $block_write;
}
if (!fclose($fp))
throw new Exception("Can't close tmp file");
unset($putData);
} else {
if (!($fp = fopen($tmpFileName, "a")))
throw new Exception("Can't write to tmp file");
while ($data = fread($putData, $CHUNK)) {
$chunk_read = strlen($data);
if (($block_write = fwrite($fp, $data)) != $chunk_read)
throw new Exception("Can't write more to tmp file");
$tot_write += $block_write;
}
if (!fclose($fp))
throw new Exception("Can't close tmp file");
unset($putData);
}
if ($tot_write != $file_size)
throw new Exception("Wrong file size");
$md5_arr = explode(' ', exec("md5sum $tmpFileName"));
$md5 = $md5sum_arr[0];
if ($md5 != $md5sum)
throw new Exception("Wrong md5");
} catch (Exception $e) {
echo '', $e->getMessage(), "\n";
}
?>
Oscar Fernandez Sierra ¶3 years ago
This is what worked for me. There are many examples in the web that don't work. I found in https://lornajane.net/posts/2009/putting-data-fields-with-php-curl.IMPORTANT: You should not use the code curl_setopt($ch, CURLOPT_PUT, true);even if it seems to be the right option (it would be the right option for a POST request, with CURLOPT_POST, but it does not work for a PUT request).Notice that the constant CURLOPT_CUSTOMREQUEST is used instead of CURLOPT_PUT, and that the value used is "PUT" instead of true.<?php $url = "....."; $data = array("a" => $a); $ch = curl_init($url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT"); curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data)); $response = curl_exec($ch); if ( ! $response) { return false; }
polygon dot co dot in at gmail dot com ¶2 years ago
I was confused with file uploads using the PUT method.My concern was why can't we upload multiple files using the PUT method with streamsPUT data comes in on the stdin stream$putdata = fopen("php://input", "r");Note the $putdata is a file pointer to the file content that is being uploaded.The data is received on the server on the fly (which means available as it is received)Secondly, when we are using parse_str(file_get_contents("php://input")).This means the data is completely received on the server end and is then made available to the script.When using fopen() one cant parse the data. This can be used when uploading a large file.The file may range from 100's of MBs to Gigs where streams plays a major role.Streams make the file data available to script in chunks instead of first saving in the temp folder.Hence, when using $putdata = fopen("php://input", "r"); one can't pass the payload as well.If someone wants to pass the payload the only option is in the URL query string.
San ¶11 years ago
Instead of using fread fwrite to save uploaded content to a file.stream_copy_to_stream is much cleaner.
willy at kochkonsult dot no ¶3 years ago
All the example code I found for using PUT with PHP always used a default hard-coded file extension for the incoming stream.The filename from the incoming file PUT request can't be found anywhere from the incoming request (at least I couldn't find it) but mimetype can be found in the $_SERVER global variable.I used this code to get the correct file extension:$mimeType = $_SERVER['HTTP_CONTENT_TYPE'];if ($mimeType!='application/pdf') { header('HTTP/1.1 405 Only PDF files allowed'); echo("Only PDF files are allowed for upload - this file is ".$mimeType); die(); }else $fileExtension = 'pdf';If you have an Apache Tika server available, that would be the best option to analyze the file content to get the mimetype, but that might not be in scope for everyone :-)