Как я могу использовать Curl для загрузки файла в PHP, если для заголовков установлено значение true? могу ли я получить имя файла и расширение файла?
Пример кода PHP:
curl_setopt ($ch, CURLOPT_HEADER, 1); $fp = fopen($strFilePath, 'w'); curl_setopt($ch, CURLOPT_FILE, $fp);
Загрузите файл или веб-страницу с помощью PHP cURL и сохраните его в файл
<?php /** * Initialize the cURL session */ $ch = curl_init(); /** * Set the URL of the page or file to download. */ curl_setopt($ch, CURLOPT_URL, 'http://news.google.com/news?hl=en&topic=t&output=rss'); /** * Create a new file */ $fp = fopen('rss.xml', 'w'); /** * Ask cURL to write the contents to a file */ curl_setopt($ch, CURLOPT_FILE, $fp); /** * Execute the cURL session */ curl_exec ($ch); /** * Close cURL session and file */ curl_close ($ch); fclose($fp); ?>
Ниже приведен полный пример использования класса. Разбор заголовка более сложный, чем может быть, потому что я клал базу для полного хранения иерархических заголовков.
Я просто заметил, что init () должен сбрасывать намного больше переменных, если он хочет, чтобы можно было повторно использовать экземпляр для большего количества URL-адресов, но это должно по крайней мере дать вам основание загрузить файл в имя файла, отправленное сервером.
<?php /* * vim: ts=4 sw=4 fdm=marker noet tw=78 */ class curlDownloader { private $remoteFileName = NULL; private $ch = NULL; private $headers = array(); private $response = NULL; private $fp = NULL; private $debug = FALSE; private $fileSize = 0; const DEFAULT_FNAME = 'remote.out'; public function __construct($url) { $this->init($url); } public function toggleDebug() { $this->debug = !$this->debug; } public function init($url) { if( !$url ) throw new InvalidArgumentException("Need a URL"); $this->ch = curl_init(); curl_setopt($this->ch, CURLOPT_URL, $url); curl_setopt($this->ch, CURLOPT_HEADERFUNCTION, array($this, 'headerCallback')); curl_setopt($this->ch, CURLOPT_WRITEFUNCTION, array($this, 'bodyCallback')); } public function headerCallback($ch, $string) { $len = strlen($string); if( !strstr($string, ':') ) { $this->response = trim($string); return $len; } list($name, $value) = explode(':', $string, 2); if( strcasecmp($name, 'Content-Disposition') == 0 ) { $parts = explode(';', $value); if( count($parts) > 1 ) { foreach($parts AS $crumb) { if( strstr($crumb, '=') ) { list($pname, $pval) = explode('=', $crumb); $pname = trim($pname); if( strcasecmp($pname, 'filename') == 0 ) { // Using basename to prevent path injection // in malicious headers. $this->remoteFileName = basename( $this->unquote(trim($pval))); $this->fp = fopen($this->remoteFileName, 'wb'); } } } } } $this->headers[$name] = trim($value); return $len; } public function bodyCallback($ch, $string) { if( !$this->fp ) { trigger_error("No remote filename received, trying default", E_USER_WARNING); $this->remoteFileName = self::DEFAULT_FNAME; $this->fp = fopen($this->remoteFileName, 'wb'); if( !$this->fp ) throw new RuntimeException("Can't open default filename"); } $len = fwrite($this->fp, $string); $this->fileSize += $len; return $len; } public function download() { $retval = curl_exec($this->ch); if( $this->debug ) var_dump($this->headers); fclose($this->fp); curl_close($this->ch); return $this->fileSize; } public function getFileName() { return $this->remoteFileName; } private function unquote($string) { return str_replace(array("'", '"'), '', $string); } } $dl = new curlDownloader( 'https://dl.example.org/torrent/cool-movie/4358-hash/download.torrent' ); $size = $dl->download(); printf("Downloaded %u bytes to %s\n", $size, $dl->getFileName()); ?>
Я верю, что вы нашли свой ответ. Тем не менее, я хотел бы поделиться своим сценарием, который хорошо работает, отправив запрос json на сервер, который возвращает файл в двоичном формате, а затем загружает его на лету. Сохранение не требуется. Надеюсь, поможет!
ПРИМЕЧАНИЕ. Вы можете избежать преобразования почтовых данных в json.
<?php // Username or E-mail $login = 'username'; // Password $password = 'password'; // API Request $url = 'https://example.com/api'; // POST data $data = array('someTask', 24); // Convert POST data to json $data_string = json_encode($data); // initialize cURL $ch = curl_init(); curl_setopt($ch, CURLOPT_URL,$url); curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); curl_setopt($ch, CURLOPT_USERPWD, "$login:$password"); curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST"); curl_setopt($ch, CURLOPT_POSTFIELDS, $data_string); curl_setopt($ch, CURLOPT_HEADER, 1); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); // Execute cURL and store the response in a variable $file = curl_exec($ch); // Get the Header Size $header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE); // Get the Header from response $header = substr($file, 0, $header_size); // Get the Body from response $body = substr($file, $header_size); // Explode Header rows into an array $header_items = explode("\n", $header); // Close cURL handler curl_close($ch); // define new variable for the File name $file_name = null; // find the filname in the headers. if(!preg_match('/filename="(.*?)"/', $header, $matches)){ // If filename not found do something... echo "Unable to find filename.<br>Please check the Response Headers or Header parsing!"; exit(); } else { // If filename was found assign the name to the variable above $file_name = $matches[1]; } // Check header response, if HTTP response is not 200, then display the error. if(!preg_match('/200/', $header_items[0])){ echo '<pre>'.print_r($header_items[0], true).'</pre>'; exit(); } else { // Check header response, if HTTP response is 200, then proceed further. // Set the header for PHP to tell it, we would like to download a file header('Content-Description: File Transfer'); header('Content-Type: application/octet-stream'); header('Content-Transfer-Encoding: binary'); header('Expires: 0'); header('Cache-Control: must-revalidate'); header('Pragma: public'); header('Content-Disposition: attachment; filename='.$file_name); // Echo out the file, which then should trigger the download echo $file; exit; } ?>
Чтобы получить как заголовки, так и данные отдельно, вы обычно используете как обратный вызов заголовка, так и обратный вызов тела. Как в этом примере: http://curl.haxx.se/libcurl/php/examples/callbacks.html
Чтобы получить имя файла из заголовков, вам нужно проверить заголовок Content-Disposition: и извлечь из него имя файла (если оно есть) или просто использовать часть имени файла из URL-адреса или аналогичного. Твой выбор.