Отправка файла с 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  Y88b   d88P  888    
888 888 Y88b d88P 888
888 888 Y88o88P 888
.d8888b 888 888 Y888P 888888
88K 888 888 d888b 888
"Y8888b. 888 888 d88888b 888
X88 Y88b. .d88P d88P Y88b Y88b.
88888P' "Y88888P" d88P Y88b "Y888


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