Отправка файла с 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    d8P      d8b  888b     d888   .d8888b.  
888 d8P Y8P 8888b d8888 d88P Y88b
888 d8P 88888b.d88888 888
888d88K 8888 888Y88888P888 888d888b.
8888888b "888 888 Y888P 888 888P "Y88b
888 Y88b 888 888 Y8P 888 888 888
888 Y88b 888 888 " 888 Y88b d88P
888 Y88b 888 888 888 "Y8888P"
888
d88P
888P"
Зарегистрируйтесь для добавления материалов без проверки.