Отправка файла с 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) и получить его?

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

    d8b  888888b.    888     888      d8888  
Y8P 888 "88b 888 888 d8P888
888 .88P 888 888 d8P 888
8888 8888888K. Y88b d88P d8P 888
"888 888 "Y88b Y88b d88P d88 888
888 888 888 Y88o88P 8888888888
888 888 d88P Y888P 888
888 8888888P" Y8P 888
888
d88P
888P"
Зарегистрируйтесь для добавления материалов без проверки.