尝试从 azure blob 下载文件,mime 类型问题

Posted

技术标签:

【中文标题】尝试从 azure blob 下载文件,mime 类型问题【英文标题】:trying to download file from azure blob, problems with mime type 【发布时间】:2017-06-01 22:12:09 【问题描述】:

我有以下代码在按下按钮时通过 ajax 调用下载文件。奇怪的是它实际上工作正常,给了我预期的文件,一段时间,当我重新访问以更改一些命名约定时,mime 类型给我带来了问题。下载时,它告诉我资源被解释为 Document 但与 application/octet-stream 一起传输。这些文件可以是 pdf、图像或 word 文档,我想一种方法是检查扩展名并分配正确的 mime 类型,但有没有更通用的方法,或者我可以从字节流不知何故?

try    
    // Get blob.
    $blob = $blobClient->getBlob($container, $blob_name);
    $properties = $blobClient->getBlobProperties($container, $blob_name);
    $size = $properties->getProperties()->getContentLength();
    $mime = $properties->getProperties()->getContentType();

    header("Content-type: $mime");
    header("Content-length: $size");
    header ("Content-Disposition: attachment; filename=$blob_name");
    fpassthru($blob->getContentStream());


【问题讨论】:

【参考方案1】:

您可以使用finfo() 函数来获取要下载的文件的mime-type。

这里是示例代码sn-p。

<?php

try 
    // Get blob.
    $blob = $blobClient->getBlob($container, $blob_name);
    $properties = $blobClient->getBlobProperties($container, $blob_name);
    $size = $properties->getProperties()->getContentLength();

    $content = stream_get_contents($blob->getContentStream());  
    $finfo = new finfo(FILEINFO_MIME);
    $mime = $finfo->buffer($content);

    header("Content-type: $mime");
    header("Content-length: $size");
    header ("Content-Disposition: inline; filename=$blob_name");

    print_r($content);

 catch(ServiceException $e) 

    $code = $e->getCode();
    $error_message = $e->getMessage();
    echo $code.": ".$error_message."<br />";

但是,您也可以根据文件扩展名检索文件的 MIME 类型。而且它比finfo() 函数更有效,尤其是当你有大文件要下载时。因为stream_get_contents会先把整个文件加载到内存中。

以下是从文件扩展名中获取 mime-type 的示例:

<?php

try 
    // Get blob.
    $blob = $blobClient->getBlob($container, $blob_name);
    $properties = $blobClient->getBlobProperties($container, $blob_name);
    $size = $properties->getProperties()->getContentLength();

    $value = explode('.', $blob_name);
    $extension = strtolower(end($value));
    $mime = detectByFileExtension($extension);

    header("Content-type: $mime");
    header("Content-length: $size");
    header ("Content-Disposition: inline; filename=$blob_name");

    fpassthru($blob->getContentStream());

 catch(ServiceException $e) 

    $code = $e->getCode();
    $error_message = $e->getMessage();
    echo $code.": ".$error_message."<br />";


function detectByFileExtension($extension)     
    $extensionToMimeTypeMap = getExtensionToMimeTypeMap();

    if (isset($extensionToMimeTypeMap[$extension])) 
        return $extensionToMimeTypeMap[$extension];
    
    return 'text/plain';


function getExtensionToMimeTypeMap() 
    return [
        'hqx'   => 'application/mac-binhex40',
        'cpt'   => 'application/mac-compactpro',
        'csv'   => 'text/x-comma-separated-values',
        'bin'   => 'application/octet-stream',
        'dms'   => 'application/octet-stream',
        'lha'   => 'application/octet-stream',
        'lzh'   => 'application/octet-stream',
        'exe'   => 'application/octet-stream',
        'class' => 'application/octet-stream',
        'psd'   => 'application/x-photoshop',
        'so'    => 'application/octet-stream',
        'sea'   => 'application/octet-stream',
        'dll'   => 'application/octet-stream',
        'oda'   => 'application/oda',
        'pdf'   => 'application/pdf',
        'ai'    => 'application/pdf',
        'eps'   => 'application/postscript',
        'ps'    => 'application/postscript',
        'smi'   => 'application/smil',
        'smil'  => 'application/smil',
        'mif'   => 'application/vnd.mif',
        'xls'   => 'application/vnd.ms-excel',
        'ppt'   => 'application/powerpoint',
        'pptx'  => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
        'wbxml' => 'application/wbxml',
        'wmlc'  => 'application/wmlc',
        'dcr'   => 'application/x-director',
        'dir'   => 'application/x-director',
        'dxr'   => 'application/x-director',
        'dvi'   => 'application/x-dvi',
        'gtar'  => 'application/x-gtar',
        'gz'    => 'application/x-gzip',
        'gzip'  => 'application/x-gzip',
        'php'   => 'application/x-httpd-php',
        'php4'  => 'application/x-httpd-php',
        'php3'  => 'application/x-httpd-php',
        'phtml' => 'application/x-httpd-php',
        'phps'  => 'application/x-httpd-php-source',
        'js'    => 'application/javascript',
        'swf'   => 'application/x-shockwave-flash',
        'sit'   => 'application/x-stuffit',
        'tar'   => 'application/x-tar',
        'tgz'   => 'application/x-tar',
        'z'     => 'application/x-compress',
        'xhtml' => 'application/xhtml+xml',
        'xht'   => 'application/xhtml+xml',
        'zip'   => 'application/x-zip',
        'rar'   => 'application/x-rar',
        'mid'   => 'audio/midi',
        'midi'  => 'audio/midi',
        'mpga'  => 'audio/mpeg',
        'mp2'   => 'audio/mpeg',
        'mp3'   => 'audio/mpeg',
        'aif'   => 'audio/x-aiff',
        'aiff'  => 'audio/x-aiff',
        'aifc'  => 'audio/x-aiff',
        'ram'   => 'audio/x-pn-realaudio',
        'rm'    => 'audio/x-pn-realaudio',
        'rpm'   => 'audio/x-pn-realaudio-plugin',
        'ra'    => 'audio/x-realaudio',
        'rv'    => 'video/vnd.rn-realvideo',
        'wav'   => 'audio/x-wav',
        'jpg'   => 'image/jpeg',
        'jpeg'  => 'image/jpeg',
        'jpe'   => 'image/jpeg',
        'png'   => 'image/png',
        'gif'   => 'image/gif',
        'bmp'   => 'image/bmp',
        'tiff'  => 'image/tiff',
        'tif'   => 'image/tiff',
        'svg'   => 'image/svg+xml',
        'css'   => 'text/css',
        'html'  => 'text/html',
        'htm'   => 'text/html',
        'shtml' => 'text/html',
        'txt'   => 'text/plain',
        'text'  => 'text/plain',
        'log'   => 'text/plain',
        'rtx'   => 'text/richtext',
        'rtf'   => 'text/rtf',
        'xml'   => 'application/xml',
        'xsl'   => 'application/xml',
        'mpeg'  => 'video/mpeg',
        'mpg'   => 'video/mpeg',
        'mpe'   => 'video/mpeg',
        'qt'    => 'video/quicktime',
        'mov'   => 'video/quicktime',
        'avi'   => 'video/x-msvideo',
        'movie' => 'video/x-sgi-movie',
        'doc'   => 'application/msword',
        'docx'  => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
        'dot'   => 'application/msword',
        'dotx'  => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
        'xlsx'  => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
        'word'  => 'application/msword',
        'xl'    => 'application/excel',
        'eml'   => 'message/rfc822',
        'json'  => 'application/json',
        'pem'   => 'application/x-x509-user-cert',
        'p10'   => 'application/x-pkcs10',
        'p12'   => 'application/x-pkcs12',
        'p7a'   => 'application/x-pkcs7-signature',
        'p7c'   => 'application/pkcs7-mime',
        'p7m'   => 'application/pkcs7-mime',
        'p7r'   => 'application/x-pkcs7-certreqresp',
        'p7s'   => 'application/pkcs7-signature',
        'crt'   => 'application/x-x509-ca-cert',
        'crl'   => 'application/pkix-crl',
        'der'   => 'application/x-x509-ca-cert',
        'kdb'   => 'application/octet-stream',
        'pgp'   => 'application/pgp',
        'gpg'   => 'application/gpg-keys',
        'sst'   => 'application/octet-stream',
        'csr'   => 'application/octet-stream',
        'rsa'   => 'application/x-pkcs7',
        'cer'   => 'application/pkix-cert',
        '3g2'   => 'video/3gpp2',
        '3gp'   => 'video/3gp',
        'mp4'   => 'video/mp4',
        'm4a'   => 'audio/x-m4a',
        'f4v'   => 'video/mp4',
        'webm'  => 'video/webm',
        'aac'   => 'audio/x-acc',
        'm4u'   => 'application/vnd.mpegurl',
        'm3u'   => 'text/plain',
        'xspf'  => 'application/xspf+xml',
        'vlc'   => 'application/videolan',
        'wmv'   => 'video/x-ms-wmv',
        'au'    => 'audio/x-au',
        'ac3'   => 'audio/ac3',
        'flac'  => 'audio/x-flac',
        'ogg'   => 'audio/ogg',
        'kmz'   => 'application/vnd.google-earth.kmz',
        'kml'   => 'application/vnd.google-earth.kml+xml',
        'ics'   => 'text/calendar',
        'zsh'   => 'text/x-scriptzsh',
        '7zip'  => 'application/x-7z-compressed',
        'cdr'   => 'application/cdr',
        'wma'   => 'audio/x-ms-wma',
        'jar'   => 'application/java-archive',
    ];

此外,将文件上传到 Azure 存储的最佳做法始终是为 blob 设置 Content-type,然后您可以使用上面提供的代码从 Azure 存储下载具有正确 mime 类型的文件。

下面的代码示例展示了如何将 blob 上传到具有 Content-type 的容器中:

<?php

require_once 'vendor/autoload.php';

use WindowsAzure\Common\ServicesBuilder;
use MicrosoftAzure\Storage\Blob\Models\CreateBlobOptions;

$connectionString = "DefaultEndpointsProtocol=https;AccountName=$account;AccountKey=$key";

$blobClient = ServicesBuilder::getInstance()->createBlobService($connectionString);

$filetoUpload = realpath('./image.jpg');
$content = fopen($filetoUpload, "r");
$mime = mime_content_type($filetoUpload);
$blob_name = "image.jpg";

try 
    //Upload blob
    $options = new CreateBlobOptions();
    $options->setContentType($mime);
    $blobClient->createBlockBlob("mycontainer", $blob_name, $content, $options);

catch(ServiceException $e) 
    $code = $e->getCode();
    $error_message = $e->getMessage();
    echo $code.": ".$error_message."<br />";

【讨论】:

谢谢,只需在上传时添加 mime 类型即可解决问题。非常简单,出于某种原因,一开始就不会想到这样做!

以上是关于尝试从 azure blob 下载文件,mime 类型问题的主要内容,如果未能解决你的问题,请参考以下文章

下载后如何从 azure blob 存储中删除文件

使用 Azure 函数从 Azure Blob 存储下载文件会返回不同的文件大小

下载几个文件后 Azure Blob 文件下载失败

将文件从 Azure Blob 存储下载到 Azure Linux VM

使用 SAS 将文件从 Azure Blob 存储下载到浏览器

如何使用条件从 Azure 存储下载 blob?