Отправка и получение файлов с помощью cURL в PHP
Работа с файлами через cURL в PHP
Наиболее эффективное решение: использование CURLFile (PHP 5.5+)
Для отправки файла на сервер через POST-запрос рекомендуется применять класс CURLFile. Он корректно формирует multipart/form-data, автоматически определяет MIME-тип и имя файла. Пример:
$ch = curl_init('https://example.com/upload.php');
$file = new CURLFile('/path/to/document.pdf', 'application/pdf', 'document.pdf');
$data = ['file' => $file];
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
Php curl timeout (php curl таймаут)
Пояснение шагов:
- Создаётся экземпляр CURLFile с абсолютным путём, MIME-типом и именем для отправки.
- Файл добавляется в ассоциативный массив $data как значение поля file.
- Опция CURLOPT_POST включает метод POST.
- Массив передаётся в CURLOPT_POSTFIELDS – cURL автоматически кодирует его как multipart/form-data.
- Ответ сервера сохраняется в $response.
Возможные проблемы:
- Ошибка curl error: 26 – файл не найден. Проверить путь и права доступа.
- Ошибка 413 Request Entity Too Large – превышен лимит сервера. Увеличить post_max_size и upload_max_filesize в PHP или на стороне сервера.
- Неправильный MIME-тип может вызвать отказ на принимающей стороне. Использовать mime_content_type() для определения.
Как отправить файл из строки (без временного файла)?
Иногда требуется передать динамически сгенерированное содержимое. Используется CURLFile с псевдо-путем php://temp или php://memory, но проще создать временный файл через tmpfile():
$temp = tmpfile();
fwrite($temp, 'содержимое файла');
$meta = stream_get_meta_data($temp);
$path = $meta['uri'];
$file = new CURLFile($path, 'text/plain', 'data.txt');
$data = ['upload' => $file];
// ... cURL запрос ...
fclose($temp);
Php curl ssl (php curl ssl)
Важно закрыть временный файл после запроса. Если несколько потоков, использовать curl_file_create() (псевдоним).
Как скачать файл с сервера и сохранить на диск?
Для загрузки файла используется опция CURLOPT_FILE, куда передаётся открытый файловый дескриптор:
$ch = curl_init('https://example.com/image.jpg');
$fp = fopen('/local/path/image.jpg', 'wb');
curl_setopt($ch, CURLOPT_FILE, $fp);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_exec($ch);
fclose($fp);
curl_close($ch);
Php curl ответ (ответ php curl)
Пояснения: флаг 'wb' открывает файл для бинарной записи. При ошибке записи fopen вернёт false.
Типичная ошибка: забыть закрыть дескриптор до завершения скрипта. Использовать try-finally или CURLOPT_RETURNTRANSFER с последующей записью.
Как отправить несколько файлов одновременно?
Массив значений может содержать несколько CURLFile объектов с разными ключами:
$files = [
'photo1' => new CURLFile('/path/1.jpg', 'image/jpeg', '1.jpg'),
'photo2' => new CURLFile('/path/2.png', 'image/png', '2.png'),
];
$data = array_merge(['token' => 'abc'], $files);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
Php curl authorization (php curl авторизация)
Если нужно отправить массив файлов с одним именем поля, используйте суффикс [] в ключе:
$files = [
new CURLFile(...),
new CURLFile(...),
];
$data = ['photos' => $files]; // префикс 'photos' будет преобразован в 'photos[0]', 'photos[1]'
Php curl close (php curl close)
Некоторые серверы требуют строгий формат именования. Тестировать с реальным API.
Как работать с очень большими файлами (избежать нехватки памяти)?
Для передачи больших данных (сотни мегабайт) используется потоковая передача через CURLOPT_INFILE и CURLOPT_INFILESIZE:
$fp = fopen('/path/to/largefile.iso', 'rb');
$ch = curl_init('https://upload.example.com/');
curl_setopt($ch, CURLOPT_PUT, true);
curl_setopt($ch, CURLOPT_INFILE, $fp);
curl_setopt($ch, CURLOPT_INFILESIZE, filesize('/path/to/largefile.iso'));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
fclose($fp);
curl_close($ch);
Php curl cookie (php curl cookie)
При использовании CURLOPT_PUT данные читаются из потока. Для POST с multipart лучше разбивать файл на части.
Проблема: сервер может не поддерживать PUT. Альтернатива – читать файл блоками и отправлять multipart вручную через CURLOPT_READFUNCTION.
Как получить содержимое файла в переменную, а не на диск?
Установка CURLOPT_RETURNTRANSFER в true возвращает данные как строку:
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$content = curl_exec($ch);
file_put_contents('downloaded.pdf', $content);
Php curl url (php curl url)
Это удобно для маленьких файлов, но для больших может занять всю память. Рекомендовать для файлов до 20-30 МБ.
Ошибка Cannot allocate memory при слишком больших объёмах. Использовать потоковую запись.
Как отправить файл вместе с текстовыми полями формы?
Достаточно добавить поля в тот же массив $data. cURL автоматически смешает multipart и urlencoded:
$data = [
'name' => 'John',
'avatar' => new CURLFile('avatar.png', 'image/png'),
];
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
Важно: текстовые поля должны быть строковыми, файлы – объектами CURLFile.
Если текстовое поле содержит символы вне ASCII, может возникнуть кодировка. Использовать urlencode не нужно – cURL обработает сам.
Расширенные примеры работы с файлами через cURL
Пример 1. Загрузка файла с индикатором прогресса
Функция CURLOPT_PROGRESSFUNCTION позволяет отслеживать передачу данных. Пример для отправки большого файла:
$file = new CURLFile('video.mp4', 'video/mp4');
$ch = curl_init('https://upload.endpoint');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, ['file' => $file]);
curl_setopt($ch, CURLOPT_NOPROGRESS, false);
curl_setopt($ch, CURLOPT_PROGRESSFUNCTION, function($ch, $downloadSize, $downloaded, $uploadSize, $uploaded) {
if ($uploadSize > 0) {
echo "Передано: " . round($uploaded / $uploadSize * 100, 2) . "%\n";
}
});
curl_exec($ch);
curl_close($ch);
Результат: в консоли выводятся проценты загрузки. Важно: функция вызываеться часто, не рекомендуется использовать ресурсоёмкие операции.
Пример 2. Множественная загрузка файлов с помощью curl_multi
Асинхронная отправка нескольких файлов повышает скорость. Используем curl_multi_init():
$files = [
'doc1.pdf' => ['path' => '/tmp/doc1.pdf', 'mime' => 'application/pdf'],
'img.png' => ['path' => '/tmp/img.png', 'mime' => 'image/png'],
];
$mh = curl_multi_init();
$handles = [];
foreach ($files as $name => $info) {
$ch = curl_init('https://api.example.com/upload');
$file = new CURLFile($info['path'], $info['mime'], $name);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, ['file' => $file]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_multi_add_handle($mh, $ch);
$handles[] = $ch;
}
$running = null;
do {
curl_multi_exec($mh, $running);
curl_multi_select($mh);
} while ($running > 0);
foreach ($handles as $ch) {
echo curl_multi_getcontent($ch) . "\n";
curl_multi_remove_handle($mh, $ch);
curl_close($ch);
}
curl_multi_close($mh);
Результат: ответ сервера для каждого файла выводится на экран. curl_multi работает асинхронно, но блокируется на curl_multi_select.
Пример 3. Отправка файла через FTP с cURL
cURL поддерживает протокол FTP. Загрузка файла на FTP-сервер:
$ch = curl_init('ftp://user:password@ftp.example.com/remote/file.pdf');
$fp = fopen('/local/file.pdf', 'rb');
curl_setopt($ch, CURLOPT_UPLOAD, true);
curl_setopt($ch, CURLOPT_INFILE, $fp);
curl_setopt($ch, CURLOPT_INFILESIZE, filesize('/local/file.pdf'));
curl_exec($ch);
fclose($fp);
curl_close($ch);
Для пассивного режима добавить CURLOPT_FTP_USE_EPSV, true. При ошибке авторизации проверить логин/пароль в URL.
Пример 4. Получение файла с сервера и сохранение с именем из заголовков
Некоторые серверы возвращают имя файла в заголовке Content-Disposition. Извлечение:
$ch = curl_init('https://example.com/download.php?id=123');
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
$headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
$header = substr($response, 0, $headerSize);
$body = substr($response, $headerSize);
// Парсим Content-Disposition
preg_match('/Content-Disposition:.*?filename="(.+?)"/', $header, $matches);
$filename = $matches[1] ?? 'downloaded_file';
file_put_contents($filename, $body);
curl_close($ch);
Результат: файл сохраняется с оригинальным именем. Обратите внимание на экранирование кавычек в регулярном выражении.
Пример 5. Отправка файла через PUT-запрос (простой)
PUT-метод часто используется для обновления ресурса. Пример с чтением потока:
$ch = curl_init('https://api.example.com/files/123');
$fp = fopen('new_data.bin', 'rb');
curl_setopt($ch, CURLOPT_PUT, true);
curl_setopt($ch, CURLOPT_INFILE, $fp);
curl_setopt($ch, CURLOPT_INFILESIZE, filesize('new_data.bin'));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
fclose($fp);
curl_close($ch);
echo $response;
Результат – ответ сервера (например, статус 200/201).
Пример 6. Скачивание файла с игнорированием SSL-ошибок (не рекомендуется)
Для тестовых серверов можно отключить проверку SSL:
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
Результат: соединение происходит без проверки сертификата. В продукции обязательно настроить CURLOPT_CAINFO.
Пример 7. Отправка файла с использованием CURLOPT_READFUNCTION
Если нужно передавать данные блоками из потока без создания временного файла:
$ch = curl_init('https://api.example.com/upload');
$data = 'some binary content'; // допустим, 1 МБ
$size = strlen($data);
$offset = 0;
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_READFUNCTION, function($ch, $stream, &$maxlen) use ($data, $size, &$offset) {
$remaining = $size - $offset;
$chunk = min($remaining, $maxlen);
$result = substr($data, $offset, $chunk);
$offset += $chunk;
return $result;
});
curl_setopt($ch, CURLOPT_INFILESIZE, $size);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
Результат: данные передаются без копирования в файл. Полезно для больших объёмов, когда содержимое генерируется на лету.