Intereting Posts
CodeIgniter – удалить «указатель» из URL Как вы получаете доступ к сеансу пользователей из службы в Symfony2? запуск сценариев bash в php Простая авторизация Twitter Oauth, запрашивающая учетные данные каждый раз подключение веб-сервисов PHP с Android Плагин проверки jQuery с обработчиком ajax submit не работает Как хранить ежедневные записи из таблицы mysql в другую? PHP и MySQLi close () Как обновить поле, чтобы добавить значение к существующему значению? Запуск скрипта оболочки из PHP как другого (не root) пользователя header («Content-type: text / css»); работает в Firefox и Chrome, но в Internet Explorer 9 он отображается как «text / html», Какая версия OpenSSL необходима для подписания с помощью sha256WithRSAEncryption Может кто-нибудь объяснить эту строку кода, пожалуйста? (Операторы логики и присваивания) вывод значений из базы данных в html-таблицу PHP Laravel 4 построитель запросов – со сложными левыми соединениями

Запрос данных PAT для множественной формы PHP?

Я пишу RESTful API. У меня возникают проблемы с загрузкой изображений с использованием разных глаголов.

Рассматривать:

У меня есть объект, который можно создать / изменить / удалить / просмотреть через запрос post / put / delete / get к URL. Запрос является формой нескольких частей, когда есть файл для загрузки, или application / xml, когда есть только текст для обработки.

Для обработки изображений, связанных с объектом, я делаю что-то вроде:

if(isset($_FILES['userfile'])) { $data = $this->image_model->upload_image(); if($data['error']){ $this->response(array('error' => $error['error'])); } $xml_data = (array)simplexml_load_string( urldecode($_POST['xml']) ); $object = (array)$xml_data['object']; } else { $object = $this->body('object'); } 

Основная проблема здесь заключается в попытке обработать запрос на put, очевидно, что $ _POST не содержит данные put (насколько я могу судить!).

Для справки это то, как я строю запросы:

 curl -F userfile=@./image.png -F xml="<xml><object>stuff to edit</object></xml>" http://example.com/object -X PUT 

Кто-нибудь есть идеи, как я могу получить доступ к переменной xml в моем запросе PUT?

Во-первых, $_FILES не заполняется при обработке запросов PUT. Он заполняется только PHP при обращении с запросами POST.

Вам нужно разобрать его вручную. Это относится и к «обычным» полям:

 // Fetch content and determine boundary $raw_data = file_get_contents('php://input'); $boundary = substr($raw_data, 0, strpos($raw_data, "\r\n")); // Fetch each part $parts = array_slice(explode($boundary, $raw_data), 1); $data = array(); foreach ($parts as $part) { // If this is the last part, break if ($part == "--\r\n") break; // Separate content from headers $part = ltrim($part, "\r\n"); list($raw_headers, $body) = explode("\r\n\r\n", $part, 2); // Parse the headers list $raw_headers = explode("\r\n", $raw_headers); $headers = array(); foreach ($raw_headers as $header) { list($name, $value) = explode(':', $header); $headers[strtolower($name)] = ltrim($value, ' '); } // Parse the Content-Disposition to get the field name, etc. if (isset($headers['content-disposition'])) { $filename = null; preg_match( '/^(.+); *name="([^"]+)"(; *filename="([^"]+)")?/', $headers['content-disposition'], $matches ); list(, $type, $name) = $matches; isset($matches[4]) and $filename = $matches[4]; // handle your fields here switch ($name) { // this is a file upload case 'userfile': file_put_contents($filename, $body); break; // default for all other files is to populate $data default: $data[$name] = substr($body, 0, strlen($body) - 2); break; } } } 

На каждой итерации массив $data будет заполнен вашими параметрами, а массив $headers будет заполнен заголовками для каждой части (например, Content-Type и т. Д.), А $filename будет содержать исходное имя файла, если поставляемый в запросе и применимый к полю.

Обратите внимание, что приведенное выше будет работать только для multipart типов контента. Обязательно проверьте заголовок Content-Type запроса перед использованием выше, чтобы проанализировать тело.

Пожалуйста, не удаляйте это снова, это полезно для большинства людей, приезжающих сюда! Все предыдущие ответы были частичными ответами, которые не охватывают решение, поскольку большинство людей, задающих этот вопрос, захотят.

Это берет то, что было сказано выше, и дополнительно обрабатывает несколько загрузок файлов и помещает их в $ _FILES, как и ожидалось. Чтобы это сработало, вам нужно добавить «Script PUT /put.php» на ваш виртуальный хост для проекта на документацию . Я также подозреваю, что мне придется настроить cron для очистки любых файлов .tmp.

 private function _parsePut( ) { global $_PUT; /* PUT data comes in on the stdin stream */ $putdata = fopen("php://input", "r"); /* Open a file for writing */ // $fp = fopen("myputfile.ext", "w"); $raw_data = ''; /* Read the data 1 KB at a time and write to the file */ while ($chunk = fread($putdata, 1024)) $raw_data .= $chunk; /* Close the streams */ fclose($putdata); // Fetch content and determine boundary $boundary = substr($raw_data, 0, strpos($raw_data, "\r\n")); if(empty($boundary)){ parse_str($raw_data,$data); $GLOBALS[ '_PUT' ] = $data; return; } // Fetch each part $parts = array_slice(explode($boundary, $raw_data), 1); $data = array(); foreach ($parts as $part) { // If this is the last part, break if ($part == "--\r\n") break; // Separate content from headers $part = ltrim($part, "\r\n"); list($raw_headers, $body) = explode("\r\n\r\n", $part, 2); // Parse the headers list $raw_headers = explode("\r\n", $raw_headers); $headers = array(); foreach ($raw_headers as $header) { list($name, $value) = explode(':', $header); $headers[strtolower($name)] = ltrim($value, ' '); } // Parse the Content-Disposition to get the field name, etc. if (isset($headers['content-disposition'])) { $filename = null; $tmp_name = null; preg_match( '/^(.+); *name="([^"]+)"(; *filename="([^"]+)")?/', $headers['content-disposition'], $matches ); list(, $type, $name) = $matches; //Parse File if( isset($matches[4]) ) { //if labeled the same as previous, skip if( isset( $_FILES[ $matches[ 2 ] ] ) ) { continue; } //get filename $filename = $matches[4]; //get tmp name $filename_parts = pathinfo( $filename ); $tmp_name = tempnam( ini_get('upload_tmp_dir'), $filename_parts['filename']); //populate $_FILES with information, size may be off in multibyte situation $_FILES[ $matches[ 2 ] ] = array( 'error'=>0, 'name'=>$filename, 'tmp_name'=>$tmp_name, 'size'=>strlen( $body ), 'type'=>$value ); //place in temporary directory file_put_contents($tmp_name, $body); } //Parse Field else { $data[$name] = substr($body, 0, strlen($body) - 2); } } } $GLOBALS[ '_PUT' ] = $data; return; } 

Цитирование ответа netcoder: «Обратите внимание, что приведенное выше будет работать только для типов многостраничного контента»

Чтобы работать с любым типом контента, я добавил следующие строки в решение г-на netcoder:

  // Fetch content and determine boundary $raw_data = file_get_contents('php://input'); $boundary = substr($raw_data, 0, strpos($raw_data, "\r\n")); /*...... My edit --------- */ if(empty($boundary)){ parse_str($raw_data,$data); return $data; } /* ........... My edit ends ......... */ // Fetch each part $parts = array_slice(explode($boundary, $raw_data), 1); $data = array(); ............ ...............