简体   繁体   中英

How to get the mime type of a file after using file_get_contents from a remote server

I'm reading a file in PHP from Alfresco and then outputting it to the browser. The only problem is the mime type or the extension of the file. This is the code I'm using:

<?php
ob_start();
require_once("libs/AlfrescoConnect.php");

$nomeFile = rawurldecode($_GET['nomeFile']);    
$urlDownload = $_GET['urlDownload'];
$fileDownloadUrl =
    AlfrescoConnect::$serverPath. $urlDownload .
    "&attach=true&alf_ticket=".AlfrescoConnect::getTiket();
fb($fileDownloadUrl);

$cnt = file_get_contents($fileDownloadUrl);

header("Content-type: Application/octet-stream");
header('Cache-Control: must-revalidate');
header('Content-disposition: attachment; filename=' .$nomeFile);
echo($cnt);
exit();

echo("Impossibile trovare il file");

I receive the name of the file from the get because, I don't know how to get the name from alfresco. But I have to guess the mimetype somehow. If I echo $cnt in the first characters, there are references to the fact that it is a PDF (for example on screen I see

%PDF-1.3 %âãÏÓ 2 0 obj << /Length 3 0 R /Filter /CCITTFaxDecode /DecodeParms << /K 0 /Columns 2480 /Rows 3508 >> /Type /XObject /Subtype /Image /Width 2480 /Height 3508 /BitsPerComponent 1 /ColorSpace /DeviceGray >> stream

So there must be a way to get the mime type from it with a function.

Any help is appreciated!

Edit. If anyone is interested here is a class that you can use to get the extension from the mime type.http://www.ustrem.org/en/articles/mime-type-by-extension-en/

You can use the finfo::buffer() method: http://php.net/finfo_buffer .

<?php
$finfo = new finfo(FILEINFO_MIME);
echo $finfo->buffer($cnt) . PHP_EOL;

NOTE : You could optionally use the finfo_buffer procedural function if that suites you better than using the object-oriented methodology.

You do not have to guess (aka autodetect) the MIME type.

Use $http_response_header to retrieve headers of the last file_get_contents call (or any call with http[s]:// wrapper ).

$contents = file_get_contents("https://www.example.com/");
$pattern = "/^content-type\s*:\s*(.*)$/i";
if (($header = array_values(preg_grep($pattern, $http_response_header))) &&
    (preg_match($pattern, $header[0], $match) !== false))
{
    $content_type = $match[1];
    echo "Content-Type is '$content_type'\n";
}

Parsing $http_response_header after file_get_contents is very unstable for me. In some cases, with very large number of requests one of another, I can't find 'Content-Type' in headers. But they were there.

So, I use such solution:

$content = file_get_contents($url);
$fh = fopen('php://memory', 'w+b');
fwrite($fh, $content);

$contentType = mime_content_type($fh);

fclose($fh);

Put this in a class:

/**
 * Given a string ($data) with a file's contents, guess and return the mime type
 *
 * Uses the standard unix program /usr/bin/file to handle the magic (pun intended)
 *
 * @param string $data
 */
public static function get_string_mime_type($data) {
    $file_cmd = '/usr/bin/file --brief --mime-type --no-buffer -';
    return rtrim(self::exec_write_read($file_cmd, $data));
}

/**
 * Executes $cmd, writes to $cmd's stdin, then returns what $cmd wrote to stdout
 */
private static function exec_write_read($cmd, $write, $log_errors = false) {
    $descriptorspec = array(
        0 => array("pipe", "r"),  // stdin is a pipe that $cmd will read from
        1 => array("pipe", "w"),  // stdout is a pipe that $cmd will write to
        2 => array("pipe", "w"),  // stderr is a pipe that $cmd will write to
    );

    $process = proc_open($cmd, $descriptorspec, $pipes);
    if (is_resource($process)) {
        // $pipes now looks like this:
        // 0 => writeable handle connected to child stdin
        // 1 => readable handle connected to child stdout
        // 2 => readable handle connected to child stderr

        fwrite($pipes[0], $write);
        fclose($pipes[0]);

        $output = stream_get_contents($pipes[1]);
        fclose($pipes[1]);

        if( $log_errors ){
            error_log(stream_get_contents($pipes[2]));
        }
        fclose($pipes[2]);

        // It is important that you close any pipes before calling
        // proc_close in order to avoid a deadlock
        $exit_code = proc_close($process);

        return $output;
    }
    else {
        throw new Exception("Couldn't open $cmd");
    }
}

Use cURL instead of file_get_contents, then you can see the response header, which will hopefully have the mime type.

Or you could try using this http://www.php.net/manual/en/ref.fileinfo.php or this deprecated function http://php.net/manual/en/function.mime-content-type.php

Here is a curl implementation from the filefield_sources module in Drupal. It can probably work anywhere:

<?php
  // Inspect the remote image
  // Check the headers to make sure it exists and is within the allowed size.
  $ch = curl_init();
  curl_setopt($ch, CURLOPT_URL, $url);
  curl_setopt($ch, CURLOPT_HEADER, TRUE);
  curl_setopt($ch, CURLOPT_NOBODY, TRUE);
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
  curl_setopt($ch, CURLOPT_HEADERFUNCTION, '_filefield_source_remote_parse_header');
  // Causes a warning if PHP safe mode is on.
  @curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);
  curl_exec($ch);
  $info = curl_getinfo($ch);
  curl_close($ch);

/**
 * Parse cURL header and record the filename specified in Content-Disposition.
 */
function _filefield_source_remote_parse_header(&$ch, $header) {
  if (preg_match('/Content-Disposition:.*?filename="(.+?)"/', $header, $matches)) {
    // Content-Disposition: attachment; filename="FILE NAME HERE"
    _filefield_source_remote_filename($matches[1]);
  }
  elseif (preg_match('/Content-Disposition:.*?filename=([^; ]+)/', $header, $matches)) {
    // Content-Disposition: attachment; filename=file.ext
    _filefield_source_remote_filename($matches[1]);
  }

  // This is required by cURL.
  return strlen($header);
}

/**
 * Get/set the remote file name in a static variable.
 */
function _filefield_source_remote_filename($curl_filename = NULL) {
  static $filename = NULL;
  if (isset($curl_filename)) {
    $filename = $curl_filename;
  }
  return $filename;
}

 ?>

To get the mime:

<?php
echo $info['content_type'];
?>

Code is here: http://drupal.org/project/filefield_sources

BE CAREFULL ! NOT ONLY CHECK the mimetype, but check it for malicious code !!!!!!!!!

details: PHP: How to get mimeType of a image with file_get_contents

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM