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

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

  .d888   .d8888b.   8888888b.            
d88P" d88P Y88b 888 "Y88b
888 .d88P 888 888
888888 8888" 888 888 8888b.
888 "Y8b. 888 888 "88b
888 888 888 888 888 .d888888
888 Y88b d88P 888 .d88P 888 888
888 "Y8888P" 8888888P" "Y888888


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