Отправка файла с POST-запросом через Drupal API

Сколько же я времени потратил, когда впервые столкнулся с этой задачей! И каково же было мое удивление, что Drupal из коробки, к сожалению, не имеет API для передачи файлов в POST-запросах – все заголовки и параметры запроса надо описывать самому.

Drupal имеет в своем арсенале API функцию drupal_http_request(), через которую по-хорошему и стоит осуществлять все запросы к внешним сервисам. Однако для отправки файла придется немного разобраться с параметрами этой функции. Допустим, у нас есть путь к файлу, который мы хотим отправить вместе с POST-запросом. Основная функция будет выглядеть так:

  1. /**
  2.  * Sends file to service.
  3.  *
  4.  * @param $path
  5.  */
  6. function fileUpload($path) {
  7. $params = array(
  8. // Указываем необходимые данные для передачи с запросом.
  9. 'data' => '123',
  10. );
  11.  
  12. $boundary = md5(uniqid());
  13. $post_data = array(
  14. 'name' => basename($path),
  15. 'file' => $path,
  16. );
  17.  
  18. $options = array(
  19. 'method' => 'POST',
  20. 'data' => multipartEncode($boundary, $post_data),
  21. 'headers' => array('Content-Type' => "multipart/form-data; boundary=$boundary"),
  22. 'timeout' => 30,
  23. );
  24.  
  25. $response = drupal_http_request('http://path/to/service' . '?' . drupal_http_build_query($params), $options);
  26.  
  27. return $response;
  28. }

Формирование данных для отправки файла в POST

Теперь несколько вспомогательных функций, которые помогут закодировать данные файла в нужном формате для отправки.

  1. /**
  2.  * Processes data for HTTP request.
  3.  *
  4.  * @param $boundary
  5.  * @param $params
  6.  */
  7. function multipartEncode($boundary, $params){
  8. $output = "";
  9.  
  10. foreach ($params as $key => $value){
  11. $output .= "--$boundary\r\n";
  12. if ($key == 'file'){
  13. $output .= multipartEncFile($value);
  14. } else {
  15. $output .= multipartEncText($key, $value);
  16. }
  17. }
  18. $output .="--$boundary--";
  19.  
  20. return $output;
  21. }
  22.  
  23. /**
  24.  * Encodes text for HTTP request.
  25.  *
  26.  * @param $name
  27.  * @param $value
  28.  */
  29. function multipartEncText($name, $value){
  30. return "Content-Disposition: form-data; name=\"$name\"\r\n\r\n$value\r\n";
  31. }
  32.  
  33. /**
  34.  * Encodes file data for HTTP request.
  35.  *
  36.  * @param $path
  37.  */
  38. function multipartEncFile($path){
  39. if (substr($path, 0, 1) == "@") {
  40. $path = substr($path, 1);
  41. }
  42. $filename = basename($path);
  43. $mimetype = "application/octet-stream";
  44. $data = "Content-Disposition: form-data; name=\"file\"; filename=\"$filename\"\r\n";
  45. $data .= "Content-Transfer-Encoding: binary\r\n";
  46. $data .= "Content-Type: $mimetype\r\n\r\n";
  47. $data .= file_get_contents($path) . "\r\n";
  48.  
  49. return $data;
  50. }

Да, код не претендует на гениальность и соответствие стандартам кодирования. Я сам, признаюсь, пока еще не вникал в тонкости его работы, но он у меня работает – а это главное. Это как-нибудь потом разберусь, как будет свободное время, что значит каждый параметр и строчка в функциях кодирования данных файла для передачи c POST-запросом.

Комментарии

Аватар пользователя Николай
Николай

Подскажите, а как сделать обратное действие, то есть отправить запрос на получение файла (.txt) и получить его?

Добавить комментарий

                888  888     888      
888 888 888
888 888 888
888 888 .d88888 888888 88888b.
888 888 d88" 888 888 888 "88b
Y88 88P 888 888 888 888 888
Y8bd8P Y88b 888 Y88b. 888 888
Y88P "Y88888 "Y888 888 888


Зарегистрируйтесь для добавления материалов без проверки.