downloads | documentation | faq | getting help | mailing lists | licenses | wiki | reporting bugs | php.net sites | links | conferences | my php.net

search for in the

Работа с удаленными файлами> <Загрузка на сервер нескольких файлов
[edit] Last updated: Fri, 25 May 2012

view this page in

Поддержка метода PUT

PHP поддерживает загрузку файлов методом HTTP PUT, который используется в некоторых клиентах для загрузки файлов на сервер. Запросы PUT намного проще, чем обыкновенная POST загрузка файла на сервер и выглядят примерно так:

PUT /path/filename.html HTTP/1.1

Такой вызов означает, что удаленный клиент хотел бы сохранить файл под именем /path/filename.html в дереве каталогов вашего веб-сервера. Очевидно, что возможность клиента автоматически перезаписывать файлы веб-сервера при помощи Apache или PHP не является хорошим решением. Поэтому для того, чтобы обрабатывать такие запросы, вам необходимо указать веб-серверу PHP-скрипт, которому вы доверяете их обработку. В веб-сервере Apache вы можете сделать это, используя директиву Script. Как правило, эта директива расположена внутри блока <Directory> или же внутри блока <VirtualHost>. Сама запись выглядит следующим образом:

Script PUT /put.php

Это указывает веб-серверу Apache на необходимость перенаправлять все PUT-запросы, контекст которых совпадает с контекстом, в которым вы разместили эту строку, в файл put.php. Предполагается, что файлы с расширением .php обрабатываются, как PHP-скрипты, и что сам PHP установлен и работает. Ресурсом назначения для всех PUT-запросов на этот скрипт должен быть сам скрипт, а не имя файла, которое должен иметь загружаемый файл.

Внутри вашего файла put.php file вы можете поместить что-нибудь похожее на следующий пример. Он скопирует содержимое загруженного файла в файл myputfile.ext на сервер. Возможно, вам понадобится осуществить несколько проверок и/или авторизовать пользователя перед выполнением копирования этого файла.

Пример #1 Saving HTTP PUT files

<?php
/* PUT данные приходят в потоке ввода stdin */
$putdata fopen("php://input""r");

/* Открываем файл на чтение */
$fp fopen("myputfile.ext""w");

/* Читаем 1 KB данных за один раз
   и пишем в файл */
while ($data fread($putdata1024))
  
fwrite($fp$data);

/* Закрываем потоки */
fclose($fp);
fclose($putdata);
?>



add a note add a note User Contributed Notes Поддержка метода PUT
micronix at gmx dot net 10-Sep-2010 07:43
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.");

           
// now the params can be used like any other variable
            // see below after input has finished

           
$tot_write = 0;
           
$tmpFileName = "/var/dev/tmp/PUT_FILE";
           
// Create a temp file
           
if (!is_file($tmpFileName)) {
               
fclose(fopen($tmpFileName, "x")); //create the file and close it
                // Open the file for writing
               
if (!($fp = fopen($tmpFileName, "w")))
                    throw new
Exception("Can't write to tmp file");

               
// Read the data a chunk at a time and write to the 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 {
               
// Open the file for writing
               
if (!($fp = fopen($tmpFileName, "a")))
                    throw new
Exception("Can't write to tmp file");

               
// Read the data a chunk at a time and write to the 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);
            }

           
// Check file length and MD5
           
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";
        }
?>
yaogzhan at gmail dot com 14-Dec-2005 04:01
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.
warhog at warhog dot net 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)
warhog at warhog dot net 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
gherson 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);
?>
gomez_NOSPAM_pixline_dot_net 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.
mikeb at mikebanahan dot com 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.
php at dreier dot nu 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.

 
show source | credits | stats | sitemap | contact | advertising | mirror sites