Sử dụng .NET, làm thế nào bạn có thể tìm thấy loại mime của một tệp dựa trên chữ ký tệp không phải là phần mở rộng


241

Tôi đang tìm kiếm một cách đơn giản để có được một loại mime trong đó phần mở rộng tệp không chính xác hoặc không được cung cấp, một cái gì đó tương tự với câu hỏi này chỉ có trong .Net.


Điều này nghe có vẻ tương tự với câu hỏi này .
Greg Hewgill

22
Tôi ước tôi có thể xóa tất cả "câu trả lời giả" vẫn đang sử dụng tiện ích mở rộng tệp khi yêu cầu rõ ràng KHÔNG sử dụng tiện ích mở rộng!
Edward Olamisan

1
Đây có thể là một câu hỏi cũ, nhưng vấn đề vẫn còn. Tôi sẽ đánh giá thấp mọi câu trả lời ở đây trên cơ sở họ chỉ kiểm tra các tệp thực thi của Windows theo nội dung của chúng; Còn các tệp thực thi Linux hoặc iOS hoặc các tệp nguy hiểm thì sao?
PhillipH

@PhillipH Viết câu trả lời cho những người đó.
wazz

Câu trả lời:


83

Trong Urlmon.dll, có một chức năng được gọi là FindMimeFromData.

Từ tài liệu

Phát hiện loại MIME hoặc "đánh hơi dữ liệu" đề cập đến quá trình xác định loại MIME phù hợp từ dữ liệu nhị phân. Kết quả cuối cùng phụ thuộc vào sự kết hợp của các tiêu đề loại MIME do máy chủ cung cấp, phần mở rộng tệp và / hoặc chính dữ liệu. Thông thường, chỉ 256 byte dữ liệu đầu tiên là đáng kể.

Vì vậy, hãy đọc 256 byte đầu tiên (tối đa) từ tệp và chuyển nó tới FindMimeFromData.


6
Làm thế nào đáng tin cậy là phương pháp này?
John Bubriski

22
Theo stackoverflow.com/questions/4833113/ Mạnh , chức năng đó chỉ có thể xác định 26 loại, vì vậy tôi không nghĩ rằng nó đáng tin cậy. Ví dụ: tệp '* .docx' được xác định là 'application / x-zip-compression'.
Đức ông

54
Tôi cho rằng đó là vì docx rõ ràng là một tệp zip.
Nick Devereaux

27
Docx một tệp zip, nhưng mimetype cho .docx là "application / vnd.openxmlformats-offratedocument.word Processingml.document". Mặc dù điều này có thể được xác định từ kiểm tra chỉ nhị phân, nhưng đây có lẽ không phải là cách hiệu quả nhất để thực hiện và trong hầu hết các trường hợp, bạn sẽ phải đọc nhiều hơn 256 byte đầu tiên.
BrainSlugs83

172

Tôi đã sử dụng urlmon.dll cuối cùng. Tôi nghĩ rằng sẽ có một cách dễ dàng hơn nhưng điều này hoạt động. Tôi bao gồm mã để giúp đỡ bất kỳ ai khác và cho phép tôi tìm lại nó nếu tôi cần.

using System.Runtime.InteropServices;

...

    [DllImport(@"urlmon.dll", CharSet = CharSet.Auto)]
    private extern static System.UInt32 FindMimeFromData(
        System.UInt32 pBC,
        [MarshalAs(UnmanagedType.LPStr)] System.String pwzUrl,
        [MarshalAs(UnmanagedType.LPArray)] byte[] pBuffer,
        System.UInt32 cbSize,
        [MarshalAs(UnmanagedType.LPStr)] System.String pwzMimeProposed,
        System.UInt32 dwMimeFlags,
        out System.UInt32 ppwzMimeOut,
        System.UInt32 dwReserverd
    );

    public static string getMimeFromFile(string filename)
    {
        if (!File.Exists(filename))
            throw new FileNotFoundException(filename + " not found");

        byte[] buffer = new byte[256];
        using (FileStream fs = new FileStream(filename, FileMode.Open))
        {
            if (fs.Length >= 256)
                fs.Read(buffer, 0, 256);
            else
                fs.Read(buffer, 0, (int)fs.Length);
        }
        try
        {
            System.UInt32 mimetype;
            FindMimeFromData(0, null, buffer, 256, null, 0, out mimetype, 0);
            System.IntPtr mimeTypePtr = new IntPtr(mimetype);
            string mime = Marshal.PtrToStringUni(mimeTypePtr);
            Marshal.FreeCoTaskMem(mimeTypePtr);
            return mime;
        }
        catch (Exception e)
        {
            return "unknown/unknown";
        }
    }

3
Có lẽ bất cứ điều gì được ánh xạ trong sổ đăng ký.
mkm Hur

3
@flq, @mkm Hurm msdn.microsoft.com/en-us/l
Ahmad

6
Tôi gặp vấn đề với mã này khi lưu trữ nó trong IIS trên Windows 8. Sử dụng triển khai trên pinvoke.net (có sự khác biệt tinh tế) đã giải quyết vấn đề: pinvoke.net/default.aspx/urlmon.findmimefromdata
Rohland

2
Tôi đã thử nghiệm mã này với IIS 7 và nó không hoạt động với tôi. Tôi có một tệp CSV mà tôi đang thử nghiệm. Tôi đã thay đổi phần mở rộng của CSV (thành .png, .jpeg, v.v.) và các thay đổi bắt chước với phần mở rộng (image / png, image / jpeg). Tôi có thể sai, nhưng theo sự hiểu biết của tôi thì Urlmon.dll đã xác định mô phỏng bằng cách sử dụng siêu dữ liệu của tệp, không chỉ là phần mở rộng của nó
Connorbode

2
không hoạt động tốt cho các ứng dụng 64 bit, thay vào đó, hãy xem tại đây: stackoverflow.com/questions/18358548/NH
omer schleifer

99

Tôi đã tìm thấy một giải pháp mã hóa cứng, tôi hy vọng tôi sẽ giúp được ai đó:

public static class MIMEAssistant
{
  private static readonly Dictionary<string, string> MIMETypesDictionary = new Dictionary<string, string>
  {
    {"ai", "application/postscript"},
    {"aif", "audio/x-aiff"},
    {"aifc", "audio/x-aiff"},
    {"aiff", "audio/x-aiff"},
    {"asc", "text/plain"},
    {"atom", "application/atom+xml"},
    {"au", "audio/basic"},
    {"avi", "video/x-msvideo"},
    {"bcpio", "application/x-bcpio"},
    {"bin", "application/octet-stream"},
    {"bmp", "image/bmp"},
    {"cdf", "application/x-netcdf"},
    {"cgm", "image/cgm"},
    {"class", "application/octet-stream"},
    {"cpio", "application/x-cpio"},
    {"cpt", "application/mac-compactpro"},
    {"csh", "application/x-csh"},
    {"css", "text/css"},
    {"dcr", "application/x-director"},
    {"dif", "video/x-dv"},
    {"dir", "application/x-director"},
    {"djv", "image/vnd.djvu"},
    {"djvu", "image/vnd.djvu"},
    {"dll", "application/octet-stream"},
    {"dmg", "application/octet-stream"},
    {"dms", "application/octet-stream"},
    {"doc", "application/msword"},
    {"docx","application/vnd.openxmlformats-officedocument.wordprocessingml.document"},
    {"dotx", "application/vnd.openxmlformats-officedocument.wordprocessingml.template"},
    {"docm","application/vnd.ms-word.document.macroEnabled.12"},
    {"dotm","application/vnd.ms-word.template.macroEnabled.12"},
    {"dtd", "application/xml-dtd"},
    {"dv", "video/x-dv"},
    {"dvi", "application/x-dvi"},
    {"dxr", "application/x-director"},
    {"eps", "application/postscript"},
    {"etx", "text/x-setext"},
    {"exe", "application/octet-stream"},
    {"ez", "application/andrew-inset"},
    {"gif", "image/gif"},
    {"gram", "application/srgs"},
    {"grxml", "application/srgs+xml"},
    {"gtar", "application/x-gtar"},
    {"hdf", "application/x-hdf"},
    {"hqx", "application/mac-binhex40"},
    {"htm", "text/html"},
    {"html", "text/html"},
    {"ice", "x-conference/x-cooltalk"},
    {"ico", "image/x-icon"},
    {"ics", "text/calendar"},
    {"ief", "image/ief"},
    {"ifb", "text/calendar"},
    {"iges", "model/iges"},
    {"igs", "model/iges"},
    {"jnlp", "application/x-java-jnlp-file"},
    {"jp2", "image/jp2"},
    {"jpe", "image/jpeg"},
    {"jpeg", "image/jpeg"},
    {"jpg", "image/jpeg"},
    {"js", "application/x-javascript"},
    {"kar", "audio/midi"},
    {"latex", "application/x-latex"},
    {"lha", "application/octet-stream"},
    {"lzh", "application/octet-stream"},
    {"m3u", "audio/x-mpegurl"},
    {"m4a", "audio/mp4a-latm"},
    {"m4b", "audio/mp4a-latm"},
    {"m4p", "audio/mp4a-latm"},
    {"m4u", "video/vnd.mpegurl"},
    {"m4v", "video/x-m4v"},
    {"mac", "image/x-macpaint"},
    {"man", "application/x-troff-man"},
    {"mathml", "application/mathml+xml"},
    {"me", "application/x-troff-me"},
    {"mesh", "model/mesh"},
    {"mid", "audio/midi"},
    {"midi", "audio/midi"},
    {"mif", "application/vnd.mif"},
    {"mov", "video/quicktime"},
    {"movie", "video/x-sgi-movie"},
    {"mp2", "audio/mpeg"},
    {"mp3", "audio/mpeg"},
    {"mp4", "video/mp4"},
    {"mpe", "video/mpeg"},
    {"mpeg", "video/mpeg"},
    {"mpg", "video/mpeg"},
    {"mpga", "audio/mpeg"},
    {"ms", "application/x-troff-ms"},
    {"msh", "model/mesh"},
    {"mxu", "video/vnd.mpegurl"},
    {"nc", "application/x-netcdf"},
    {"oda", "application/oda"},
    {"ogg", "application/ogg"},
    {"pbm", "image/x-portable-bitmap"},
    {"pct", "image/pict"},
    {"pdb", "chemical/x-pdb"},
    {"pdf", "application/pdf"},
    {"pgm", "image/x-portable-graymap"},
    {"pgn", "application/x-chess-pgn"},
    {"pic", "image/pict"},
    {"pict", "image/pict"},
    {"png", "image/png"}, 
    {"pnm", "image/x-portable-anymap"},
    {"pnt", "image/x-macpaint"},
    {"pntg", "image/x-macpaint"},
    {"ppm", "image/x-portable-pixmap"},
    {"ppt", "application/vnd.ms-powerpoint"},
    {"pptx","application/vnd.openxmlformats-officedocument.presentationml.presentation"},
    {"potx","application/vnd.openxmlformats-officedocument.presentationml.template"},
    {"ppsx","application/vnd.openxmlformats-officedocument.presentationml.slideshow"},
    {"ppam","application/vnd.ms-powerpoint.addin.macroEnabled.12"},
    {"pptm","application/vnd.ms-powerpoint.presentation.macroEnabled.12"},
    {"potm","application/vnd.ms-powerpoint.template.macroEnabled.12"},
    {"ppsm","application/vnd.ms-powerpoint.slideshow.macroEnabled.12"},
    {"ps", "application/postscript"},
    {"qt", "video/quicktime"},
    {"qti", "image/x-quicktime"},
    {"qtif", "image/x-quicktime"},
    {"ra", "audio/x-pn-realaudio"},
    {"ram", "audio/x-pn-realaudio"},
    {"ras", "image/x-cmu-raster"},
    {"rdf", "application/rdf+xml"},
    {"rgb", "image/x-rgb"},
    {"rm", "application/vnd.rn-realmedia"},
    {"roff", "application/x-troff"},
    {"rtf", "text/rtf"},
    {"rtx", "text/richtext"},
    {"sgm", "text/sgml"},
    {"sgml", "text/sgml"},
    {"sh", "application/x-sh"},
    {"shar", "application/x-shar"},
    {"silo", "model/mesh"},
    {"sit", "application/x-stuffit"},
    {"skd", "application/x-koan"},
    {"skm", "application/x-koan"},
    {"skp", "application/x-koan"},
    {"skt", "application/x-koan"},
    {"smi", "application/smil"},
    {"smil", "application/smil"},
    {"snd", "audio/basic"},
    {"so", "application/octet-stream"},
    {"spl", "application/x-futuresplash"},
    {"src", "application/x-wais-source"},
    {"sv4cpio", "application/x-sv4cpio"},
    {"sv4crc", "application/x-sv4crc"},
    {"svg", "image/svg+xml"},
    {"swf", "application/x-shockwave-flash"},
    {"t", "application/x-troff"},
    {"tar", "application/x-tar"},
    {"tcl", "application/x-tcl"},
    {"tex", "application/x-tex"},
    {"texi", "application/x-texinfo"},
    {"texinfo", "application/x-texinfo"},
    {"tif", "image/tiff"},
    {"tiff", "image/tiff"},
    {"tr", "application/x-troff"},
    {"tsv", "text/tab-separated-values"},
    {"txt", "text/plain"},
    {"ustar", "application/x-ustar"},
    {"vcd", "application/x-cdlink"},
    {"vrml", "model/vrml"},
    {"vxml", "application/voicexml+xml"},
    {"wav", "audio/x-wav"},
    {"wbmp", "image/vnd.wap.wbmp"},
    {"wbmxl", "application/vnd.wap.wbxml"},
    {"wml", "text/vnd.wap.wml"},
    {"wmlc", "application/vnd.wap.wmlc"},
    {"wmls", "text/vnd.wap.wmlscript"},
    {"wmlsc", "application/vnd.wap.wmlscriptc"},
    {"wrl", "model/vrml"},
    {"xbm", "image/x-xbitmap"},
    {"xht", "application/xhtml+xml"},
    {"xhtml", "application/xhtml+xml"},
    {"xls", "application/vnd.ms-excel"},                        
    {"xml", "application/xml"},
    {"xpm", "image/x-xpixmap"},
    {"xsl", "application/xml"},
    {"xlsx","application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"},
    {"xltx","application/vnd.openxmlformats-officedocument.spreadsheetml.template"},
    {"xlsm","application/vnd.ms-excel.sheet.macroEnabled.12"},
    {"xltm","application/vnd.ms-excel.template.macroEnabled.12"},
    {"xlam","application/vnd.ms-excel.addin.macroEnabled.12"},
    {"xlsb","application/vnd.ms-excel.sheet.binary.macroEnabled.12"},
    {"xslt", "application/xslt+xml"},
    {"xul", "application/vnd.mozilla.xul+xml"},
    {"xwd", "image/x-xwindowdump"},
    {"xyz", "chemical/x-xyz"},
    {"zip", "application/zip"}
  };

  public static string GetMIMEType(string fileName)
  {
    //get file extension
    string extension = Path.GetExtension(fileName).ToLowerInvariant();

    if (extension.Length > 0 && 
        MIMETypesDictionary.ContainsKey(extension.Remove(0, 1)))
    {
      return MIMETypesDictionary[extension.Remove(0, 1)];
    }
    return "unknown/unknown";
  }
}

58
Điều này dựa trên tên tệp tuy nhiên. Nó có thể hữu ích cho ai đó, không phải OP, người muốn nó được thực hiện bởi nội dung tệp.
mandreko

4
Một tập hợp con của danh sách này cũng thuận tiện cho việc ánh xạ WebImage.ImageFormat trở lại kiểu mime. Cảm ơn!
Derrick

8
Tùy thuộc vào mục tiêu của bạn, bạn có thể muốn trả về "application / octet-stream" thay vì "unknown / unknown".
Nicolas Raoul

4
Vì bản chỉnh sửa của tôi đã bị từ chối nên tôi sẽ đăng ở đây: phần mở rộng phải ở dạng chữ thường, hoặc nó sẽ không được tìm thấy trong từ điển.
Howie

3
@ JalalAldeenSaa'd - IMHO sửa lỗi thậm chí còn tốt hơn sẽ được sử dụng StringComparer.OrdinalIgnoreCasecho trình tạo từ điển. So sánh thông thường là nhanh hơn bất biến, và bạn sẽ thoát khỏi .ToLower()và các biến thể của nó.
Ivaylo Slavov

87

Chỉnh sửa: Chỉ cần sử dụng Mime Detective

Tôi sử dụng các chuỗi mảng byte để xác định loại MIME chính xác của một tệp đã cho. Ưu điểm của việc này là chỉ nhìn vào phần mở rộng tệp của tên tệp là nếu người dùng đổi tên tệp để bỏ qua các hạn chế tải lên loại tệp nhất định, phần mở rộng tên tệp sẽ không bắt được điều này. Mặt khác, việc lấy chữ ký tệp qua mảng byte sẽ ngăn hành vi tinh quái này xảy ra.

Đây là một ví dụ trong C #:

public class MimeType
{
    private static readonly byte[] BMP = { 66, 77 };
    private static readonly byte[] DOC = { 208, 207, 17, 224, 161, 177, 26, 225 };
    private static readonly byte[] EXE_DLL = { 77, 90 };
    private static readonly byte[] GIF = { 71, 73, 70, 56 };
    private static readonly byte[] ICO = { 0, 0, 1, 0 };
    private static readonly byte[] JPG = { 255, 216, 255 };
    private static readonly byte[] MP3 = { 255, 251, 48 };
    private static readonly byte[] OGG = { 79, 103, 103, 83, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0 };
    private static readonly byte[] PDF = { 37, 80, 68, 70, 45, 49, 46 };
    private static readonly byte[] PNG = { 137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68, 82 };
    private static readonly byte[] RAR = { 82, 97, 114, 33, 26, 7, 0 };
    private static readonly byte[] SWF = { 70, 87, 83 };
    private static readonly byte[] TIFF = { 73, 73, 42, 0 };
    private static readonly byte[] TORRENT = { 100, 56, 58, 97, 110, 110, 111, 117, 110, 99, 101 };
    private static readonly byte[] TTF = { 0, 1, 0, 0, 0 };
    private static readonly byte[] WAV_AVI = { 82, 73, 70, 70 };
    private static readonly byte[] WMV_WMA = { 48, 38, 178, 117, 142, 102, 207, 17, 166, 217, 0, 170, 0, 98, 206, 108 };
    private static readonly byte[] ZIP_DOCX = { 80, 75, 3, 4 };

    public static string GetMimeType(byte[] file, string fileName)
    {

        string mime = "application/octet-stream"; //DEFAULT UNKNOWN MIME TYPE

        //Ensure that the filename isn't empty or null
        if (string.IsNullOrWhiteSpace(fileName))
        {
            return mime;
        }

        //Get the file extension
        string extension = Path.GetExtension(fileName) == null
                               ? string.Empty
                               : Path.GetExtension(fileName).ToUpper();

        //Get the MIME Type
        if (file.Take(2).SequenceEqual(BMP))
        {
            mime = "image/bmp";
        }
        else if (file.Take(8).SequenceEqual(DOC))
        {
            mime = "application/msword";
        }
        else if (file.Take(2).SequenceEqual(EXE_DLL))
        {
            mime = "application/x-msdownload"; //both use same mime type
        }
        else if (file.Take(4).SequenceEqual(GIF))
        {
            mime = "image/gif";
        }
        else if (file.Take(4).SequenceEqual(ICO))
        {
            mime = "image/x-icon";
        }
        else if (file.Take(3).SequenceEqual(JPG))
        {
            mime = "image/jpeg";
        }
        else if (file.Take(3).SequenceEqual(MP3))
        {
            mime = "audio/mpeg";
        }
        else if (file.Take(14).SequenceEqual(OGG))
        {
            if (extension == ".OGX")
            {
                mime = "application/ogg";
            }
            else if (extension == ".OGA")
            {
                mime = "audio/ogg";
            }
            else
            {
                mime = "video/ogg";
            }
        }
        else if (file.Take(7).SequenceEqual(PDF))
        {
            mime = "application/pdf";
        }
        else if (file.Take(16).SequenceEqual(PNG))
        {
            mime = "image/png";
        }
        else if (file.Take(7).SequenceEqual(RAR))
        {
            mime = "application/x-rar-compressed";
        }
        else if (file.Take(3).SequenceEqual(SWF))
        {
            mime = "application/x-shockwave-flash";
        }
        else if (file.Take(4).SequenceEqual(TIFF))
        {
            mime = "image/tiff";
        }
        else if (file.Take(11).SequenceEqual(TORRENT))
        {
            mime = "application/x-bittorrent";
        }
        else if (file.Take(5).SequenceEqual(TTF))
        {
            mime = "application/x-font-ttf";
        }
        else if (file.Take(4).SequenceEqual(WAV_AVI))
        {
            mime = extension == ".AVI" ? "video/x-msvideo" : "audio/x-wav";
        }
        else if (file.Take(16).SequenceEqual(WMV_WMA))
        {
            mime = extension == ".WMA" ? "audio/x-ms-wma" : "video/x-ms-wmv";
        }
        else if (file.Take(4).SequenceEqual(ZIP_DOCX))
        {
            mime = extension == ".DOCX" ? "application/vnd.openxmlformats-officedocument.wordprocessingml.document" : "application/x-zip-compressed";
        }

        return mime;
    }


}

Lưu ý rằng tôi đã xử lý các loại tệp DOCX khác nhau vì DOCX thực sự chỉ là một tệp ZIP. Trong kịch bản này, tôi chỉ cần kiểm tra phần mở rộng tập tin một khi tôi xác minh rằng nó có trình tự đó. Ví dụ này không hoàn chỉnh đối với một số người, nhưng bạn có thể dễ dàng thêm chính mình.

Nếu bạn muốn thêm nhiều loại MIME, bạn có thể nhận được các chuỗi mảng byte của nhiều loại tệp khác nhau từ đây . Ngoài ra, đây là một tài nguyên tốt liên quan đến chữ ký tập tin.

Những gì tôi làm rất nhiều lần nếu tất cả các lỗi khác là bước qua một số tệp thuộc một loại cụ thể mà tôi đang tìm kiếm và tìm kiếm một mẫu trong chuỗi byte của các tệp. Cuối cùng, đây vẫn là xác minh cơ bản và không thể được sử dụng để chứng minh 100% các loại tệp.


1
Cảm ơn @ROFLwTIME - Tôi đã cải thiện điều này một chút để xử lý khi chúng tôi có một mảng byte nhưng không có tên tệp / phần mở rộng. (Tất nhiên đối với một số loại mime, nó sẽ cần phải mặc định hoặc cần được tăng cường hơn nữa để xác định chính xác). Nhưng nếu bất cứ ai muốn tôi gửi mã xin vui lòng cho tôi biết.
Chris

+1 để sử dụng byte. Bây giờ người ta thậm chí có thể lấy số byte dự kiến ​​cho một loại mime cụ thể để kiểm tra nó (không phải là mặc định là 256). Tuy nhiên, tôi sẽ sử dụng một cấu trúc ở đây, với phần mở rộng, byte và mime / type làm thuộc tính và có thể giữ một từ điển các cấu trúc được xác định trước. Điều này sẽ giúp tôi tiết kiệm vô tận nếu kiểm tra nếu không
Ivaylo Slavov

2
Vấn đề với cách tiếp cận này là, ví dụ, một tệp văn bản bắt đầu bằng "MZ" sẽ được hiểu là tệp .EXE. Nói cách khác, ít nhất bạn nên xem xét gia hạn trong mọi trường hợp, cộng với chữ ký dài hơn hoặc các định dạng theo định dạng để tránh dương tính giả.
Néstor Sánchez A.

1
@Nutshell Tôi tin rằng XLS có 0 byte ở cuối trong khi DOC thì không, vì vậy hãy kiểm tra XLS trước, sau đó là DOC. Đối với XLSX / DOCX, chúng có chung chữ ký (ZIP), vì vậy để phân biệt những thứ bạn sẽ cần đi sâu hơn đọc tiêu đề. Ví dụ: các tệp XLSX có chuỗi "xl / _ bọn / workbook.xml. tội" gần tiêu đề trong khi các tệp DOCX có chuỗi "word / _reb / ​​document.xml. tội" gần tiêu đề. Đây chỉ là một trong nhiều cách để thử và phân biệt các loại cụ thể đó và chắc chắn nó sẽ không bao gồm 100% các kịch bản. (ví dụ: tệp Zip có tệp DOCX / XLSX trong đó)
ROFLwTIME

7
Này các cậu. Tôi là người đã chia rẽ FileTypeDetective ban đầu thành MimeDetective tại github. Tôi hạnh phúc nếu nó hữu ích. Và ivv đã nói chuyện với trailmax của nhà phát triển. Chúng tôi đã thay đổi giấy phép thành MIT!
Muraad Nofal

36

Nếu bạn đang sử dụng .NET Framework 4.5 trở lên, giờ đây đã có phương thức MimeMapping.GetMimeMapping (tên tệp) sẽ trả về một chuỗi có ánh xạ Mime chính xác cho tên tệp đã truyền. Lưu ý rằng điều này sử dụng phần mở rộng tệp, không phải dữ liệu trong chính tệp.

Tài liệu có tại http://msdn.microsoft.com/en-us/l Library / system.web.mimemicking.getmimemicking


3
Điều này làm việc cho tôi và nó chỉ mất một dòng mã. var mimetype = System.Web.MimeMapping.GetMimeMapping(<pathToFile>);
Garry

50
Điều này không trả lời câu hỏi ban đầu "nếu phần mở rộng tập tin không chính xác hoặc bị thiếu". GetMimeMapping chỉ sử dụng một từ điển tĩnh của các mục mở rộng và mime.
Barry Hagan

1
Tôi tìm thấy lớp này nếu rất hữu ích :)
TeYoU

1
Không có sẵn trong .net-core. Thay vào đó, bạn có thể sử dụng: chuỗi contentType; FileExtensionContentTypeProvider (). TryGetContentType (tên tệp, out contentType); contentType = contentType ?? "Ứng dụng / octet-stream";
John Pankowicz

2
Thông thường, tôi không hạ thấp câu trả lời nhưng vì câu trả lời sai lầm này, tôi đã làm như vậy. Câu hỏi nói về việc không tin vào phần mở rộng tên tệp
Anigate

26

Bạn cũng có thể xem trong sổ đăng ký.

    using System.IO;
    using Microsoft.Win32;

    string GetMimeType(FileInfo fileInfo)
    {
        string mimeType = "application/unknown";

        RegistryKey regKey = Registry.ClassesRoot.OpenSubKey(
            fileInfo.Extension.ToLower()
            );

        if(regKey != null)
        {
            object contentType = regKey.GetValue("Content Type");

            if(contentType != null)
                mimeType = contentType.ToString();
        }

        return mimeType;
    }

Bằng cách này hay cách khác bạn sẽ phải truy cập vào cơ sở dữ liệu của MIME - cho dù chúng được ánh xạ từ các tiện ích mở rộng hoặc số ma thuật có phần tầm thường - sổ đăng ký windows là một nơi như vậy. Đối với một giải pháp độc lập nền tảng mặc dù người ta sẽ phải gửi DB này với mã (hoặc dưới dạng thư viện độc lập).


1
@Rabbi Mặc dù câu hỏi chỉ dành riêng cho nội dung tệp và không phải phần mở rộng, câu trả lời này vẫn có thể hữu ích cho những người khác (chẳng hạn như tôi), những người đang đi qua. Ngay cả khi một câu trả lời như thế này khó có thể được chấp nhận, vẫn rất tốt để có thông tin.
BrainSlugs83

5
điều này không chỉ đơn giản là có được mime dựa trên phần mở rộng của tên tệp? Điều gì xảy ra nếu tập tin là một .docx và một số chú hề quyết định đổi tên nó thành .doc? bạn chắc chắn đã nhận được loại mime sai.
kolin

8
@kolin, bạn hoàn toàn chính xác, nhưng như câu nói "hãy làm cho nó thành bằng chứng ngu ngốc và ai đó sẽ làm cho một kẻ ngốc tốt hơn." :)
Serguei

Khi làm việc với vai trò Windows Azure Web hoặc bất kỳ máy chủ nào khác chạy ứng dụng của bạn trong Limited Trust - Đừng quên rằng bạn sẽ không được phép truy cập vào sổ đăng ký. Kết hợp từ điển try-Catch-for-registry và in-memory như câu trả lời của Anykey trông giống như một giải pháp tốt có cả hai.
Ognyan Dimitrov

8

Tôi sử dụng một giải pháp lai:

    using System.Runtime.InteropServices;

    [DllImport (@"urlmon.dll", CharSet = CharSet.Auto)]
    private extern static System.UInt32 FindMimeFromData(
        System.UInt32 pBC, 
        [MarshalAs(UnmanagedType.LPStr)] System.String pwzUrl,
        [MarshalAs(UnmanagedType.LPArray)] byte[] pBuffer,
        System.UInt32 cbSize,
        [MarshalAs(UnmanagedType.LPStr)] System.String pwzMimeProposed,
        System.UInt32 dwMimeFlags,
        out System.UInt32 ppwzMimeOut,
        System.UInt32 dwReserverd
    );

    private string GetMimeFromRegistry (string Filename)
    {
        string mime = "application/octetstream";
        string ext = System.IO.Path.GetExtension(Filename).ToLower();
        Microsoft.Win32.RegistryKey rk = Microsoft.Win32.Registry.ClassesRoot.OpenSubKey(ext);
        if (rk != null && rk.GetValue("Content Type") != null)
            mime = rk.GetValue("Content Type").ToString();
        return mime;
    }

    public string GetMimeTypeFromFileAndRegistry (string filename)
    {
        if (!File.Exists(filename))
        {
           return GetMimeFromRegistry (filename);
        }

        byte[] buffer = new byte[256];

        using (FileStream fs = new FileStream(filename, FileMode.Open))
        {
            if (fs.Length >= 256)
                fs.Read(buffer, 0, 256);
            else
                fs.Read(buffer, 0, (int)fs.Length);
        }

        try
        {            
            System.UInt32 mimetype;

            FindMimeFromData(0, null, buffer, 256, null, 0, out mimetype, 0);

            System.IntPtr mimeTypePtr = new IntPtr(mimetype);

            string mime = Marshal.PtrToStringUni(mimeTypePtr);

            Marshal.FreeCoTaskMem(mimeTypePtr);

            if (string.IsNullOrWhiteSpace (mime) || 
                mime =="text/plain" || mime == "application/octet-stream")                    
            {
                return GetMimeFromRegistry (filename);
            }

            return mime;
        }
        catch (Exception e)
        {
            return GetMimeFromRegistry (filename);
        }
    }

1
Cảm ơn mã. Nó đã làm việc một phần. Đối với cả tệp "doc" và "tif", nó trả về "application / octet-stream". Có bất kỳ lựa chọn khác avilable.
Pranav Shah

Sẽ thật gọn gàng khi thấy một giải pháp lai của từ điển mở rộng và urlmon ở trên.
BrainSlugs83

@PranavShah, lưu ý rằng kiến ​​thức về các loại mime của máy chủ (những thứ được trả về bởi tra cứu sổ đăng ký) là chủ quan đối với phần mềm nào được cài đặt trên máy chủ. Cài đặt windows cơ bản hoặc máy chủ web chuyên dụng không đáng tin cậy để biết các loại phần mềm bên thứ 3 không cần cài đặt. Tuy nhiên, nó nên biết một .doctập tin là gì.
Ivaylo Slavov

6

HeyRed.Mime.MimeGuesser.GuessMimeType từ Nuget sẽ là giải pháp tối ưu nếu bạn muốn lưu trữ giải pháp ASP.NET của mình trên các môi trường không có cửa sổ.

Ánh xạ mở rộng tập tin là rất không an toàn. Nếu kẻ tấn công sẽ tải lên các tiện ích mở rộng không hợp lệ, từ điển ánh xạ sẽ cho phép các tệp thực thi được phân phối bên trong các tệp .jpg. Do đó, luôn luôn sử dụng thư viện đánh hơi nội dung để biết loại nội dung thực.

 public  static string MimeTypeFrom(byte[] dataBytes, string fileName)
 {
        var contentType = HeyRed.Mime.MimeGuesser.GuessMimeType(dataBytes);
        if (string.IsNullOrEmpty(contentType))
        {
            return HeyRed.Mime.MimeTypesMap.GetMimeType(fileName);
        }
  return contentType;

1
Cho đến nay, thư viện tốt nhất mà tôi đã thử. Tìm thấy loại nội dung cho mọi tập tin tôi đặt trong thư mục của tôi. + .net Hỗ trợ lõi!
TS

3

Tôi nghĩ câu trả lời đúng là sự kết hợp giữa câu trả lời của Steve Morgan và Serguei. Đó là cách Internet Explorer thực hiện. Cuộc gọi pinvoke chỉ FindMimeFromDatahoạt động với 26 loại mime được mã hóa cứng. Ngoài ra, nó sẽ cung cấp các loại mime mơ hồ (như text/plainhoặcapplication/octet-stream ) mặc dù có thể tồn tại một loại mime cụ thể hơn, phù hợp hơn. Nếu nó không cung cấp loại mime tốt, bạn có thể vào sổ đăng ký để biết loại mime cụ thể hơn. Sổ đăng ký máy chủ có thể có nhiều loại mime cập nhật hơn.

Tham khảo: http://msdn.microsoft.com/en-us/l Library / ms775147 (VS85) .aspx


3

Lớp này sử dụng các câu trả lời trước để thử theo 3 cách khác nhau: mã hóa dựa trên tiện ích mở rộng, API FindMimeFromData và sử dụng sổ đăng ký.

using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;

using Microsoft.Win32;

namespace YourNamespace
{
    public static class MimeTypeParser
    {
        [DllImport(@"urlmon.dll", CharSet = CharSet.Auto)]
        private extern static System.UInt32 FindMimeFromData(
                System.UInt32 pBC,
                [MarshalAs(UnmanagedType.LPStr)] System.String pwzUrl,
                [MarshalAs(UnmanagedType.LPArray)] byte[] pBuffer,
                System.UInt32 cbSize,
                [MarshalAs(UnmanagedType.LPStr)] System.String pwzMimeProposed,
                System.UInt32 dwMimeFlags,
                out System.UInt32 ppwzMimeOut,
                System.UInt32 dwReserverd
        );

        public static string GetMimeType(string sFilePath)
        {
            string sMimeType = GetMimeTypeFromList(sFilePath);

            if (String.IsNullOrEmpty(sMimeType))
            {
                sMimeType = GetMimeTypeFromFile(sFilePath);

                if (String.IsNullOrEmpty(sMimeType))
                {
                    sMimeType = GetMimeTypeFromRegistry(sFilePath);
                }
            }

            return sMimeType;
        }

        public static string GetMimeTypeFromList(string sFileNameOrPath)
        {
            string sMimeType = null;
            string sExtensionWithoutDot = Path.GetExtension(sFileNameOrPath).Substring(1).ToLower();

            if (!String.IsNullOrEmpty(sExtensionWithoutDot) && spDicMIMETypes.ContainsKey(sExtensionWithoutDot))
            {
                sMimeType = spDicMIMETypes[sExtensionWithoutDot];
            }

            return sMimeType;
        }

        public static string GetMimeTypeFromRegistry(string sFileNameOrPath)
        {
            string sMimeType = null;
            string sExtension = Path.GetExtension(sFileNameOrPath).ToLower();
            RegistryKey pKey = Registry.ClassesRoot.OpenSubKey(sExtension);

            if (pKey != null && pKey.GetValue("Content Type") != null)
            {
                sMimeType = pKey.GetValue("Content Type").ToString();
            }

            return sMimeType;
        }

        public static string GetMimeTypeFromFile(string sFilePath)
        {
            string sMimeType = null;

            if (File.Exists(sFilePath))
            {
                byte[] abytBuffer = new byte[256];

                using (FileStream pFileStream = new FileStream(sFilePath, FileMode.Open))
                {
                    if (pFileStream.Length >= 256)
                    {
                        pFileStream.Read(abytBuffer, 0, 256);
                    }
                    else
                    {
                        pFileStream.Read(abytBuffer, 0, (int)pFileStream.Length);
                    }
                }

                try
                {
                    UInt32 unMimeType;

                    FindMimeFromData(0, null, abytBuffer, 256, null, 0, out unMimeType, 0);

                    IntPtr pMimeType = new IntPtr(unMimeType);
                    string sMimeTypeFromFile = Marshal.PtrToStringUni(pMimeType);

                    Marshal.FreeCoTaskMem(pMimeType);

                    if (!String.IsNullOrEmpty(sMimeTypeFromFile) && sMimeTypeFromFile != "text/plain" && sMimeTypeFromFile != "application/octet-stream")
                    {
                        sMimeType = sMimeTypeFromFile;
                    }
                }
                catch {}
            }

            return sMimeType;
        }

        private static readonly Dictionary<string, string> spDicMIMETypes = new Dictionary<string, string>
        {
            {"ai", "application/postscript"},
            {"aif", "audio/x-aiff"},
            {"aifc", "audio/x-aiff"},
            {"aiff", "audio/x-aiff"},
            {"asc", "text/plain"},
            {"atom", "application/atom+xml"},
            {"au", "audio/basic"},
            {"avi", "video/x-msvideo"},
            {"bcpio", "application/x-bcpio"},
            {"bin", "application/octet-stream"},
            {"bmp", "image/bmp"},
            {"cdf", "application/x-netcdf"},
            {"cgm", "image/cgm"},
            {"class", "application/octet-stream"},
            {"cpio", "application/x-cpio"},
            {"cpt", "application/mac-compactpro"},
            {"csh", "application/x-csh"},
            {"css", "text/css"},
            {"dcr", "application/x-director"},
            {"dif", "video/x-dv"},
            {"dir", "application/x-director"},
            {"djv", "image/vnd.djvu"},
            {"djvu", "image/vnd.djvu"},
            {"dll", "application/octet-stream"},
            {"dmg", "application/octet-stream"},
            {"dms", "application/octet-stream"},
            {"doc", "application/msword"},
            {"docx","application/vnd.openxmlformats-officedocument.wordprocessingml.document"},
            {"dotx", "application/vnd.openxmlformats-officedocument.wordprocessingml.template"},
            {"docm","application/vnd.ms-word.document.macroEnabled.12"},
            {"dotm","application/vnd.ms-word.template.macroEnabled.12"},
            {"dtd", "application/xml-dtd"},
            {"dv", "video/x-dv"},
            {"dvi", "application/x-dvi"},
            {"dxr", "application/x-director"},
            {"eps", "application/postscript"},
            {"etx", "text/x-setext"},
            {"exe", "application/octet-stream"},
            {"ez", "application/andrew-inset"},
            {"gif", "image/gif"},
            {"gram", "application/srgs"},
            {"grxml", "application/srgs+xml"},
            {"gtar", "application/x-gtar"},
            {"hdf", "application/x-hdf"},
            {"hqx", "application/mac-binhex40"},
            {"htc", "text/x-component"},
            {"htm", "text/html"},
            {"html", "text/html"},
            {"ice", "x-conference/x-cooltalk"},
            {"ico", "image/x-icon"},
            {"ics", "text/calendar"},
            {"ief", "image/ief"},
            {"ifb", "text/calendar"},
            {"iges", "model/iges"},
            {"igs", "model/iges"},
            {"jnlp", "application/x-java-jnlp-file"},
            {"jp2", "image/jp2"},
            {"jpe", "image/jpeg"},
            {"jpeg", "image/jpeg"},
            {"jpg", "image/jpeg"},
            {"js", "application/x-javascript"},
            {"kar", "audio/midi"},
            {"latex", "application/x-latex"},
            {"lha", "application/octet-stream"},
            {"lzh", "application/octet-stream"},
            {"m3u", "audio/x-mpegurl"},
            {"m4a", "audio/mp4a-latm"},
            {"m4b", "audio/mp4a-latm"},
            {"m4p", "audio/mp4a-latm"},
            {"m4u", "video/vnd.mpegurl"},
            {"m4v", "video/x-m4v"},
            {"mac", "image/x-macpaint"},
            {"man", "application/x-troff-man"},
            {"mathml", "application/mathml+xml"},
            {"me", "application/x-troff-me"},
            {"mesh", "model/mesh"},
            {"mid", "audio/midi"},
            {"midi", "audio/midi"},
            {"mif", "application/vnd.mif"},
            {"mov", "video/quicktime"},
            {"movie", "video/x-sgi-movie"},
            {"mp2", "audio/mpeg"},
            {"mp3", "audio/mpeg"},
            {"mp4", "video/mp4"},
            {"mpe", "video/mpeg"},
            {"mpeg", "video/mpeg"},
            {"mpg", "video/mpeg"},
            {"mpga", "audio/mpeg"},
            {"ms", "application/x-troff-ms"},
            {"msh", "model/mesh"},
            {"mxu", "video/vnd.mpegurl"},
            {"nc", "application/x-netcdf"},
            {"oda", "application/oda"},
            {"ogg", "application/ogg"},
            {"pbm", "image/x-portable-bitmap"},
            {"pct", "image/pict"},
            {"pdb", "chemical/x-pdb"},
            {"pdf", "application/pdf"},
            {"pgm", "image/x-portable-graymap"},
            {"pgn", "application/x-chess-pgn"},
            {"pic", "image/pict"},
            {"pict", "image/pict"},
            {"png", "image/png"}, 
            {"pnm", "image/x-portable-anymap"},
            {"pnt", "image/x-macpaint"},
            {"pntg", "image/x-macpaint"},
            {"ppm", "image/x-portable-pixmap"},
            {"ppt", "application/vnd.ms-powerpoint"},
            {"pptx","application/vnd.openxmlformats-officedocument.presentationml.presentation"},
            {"potx","application/vnd.openxmlformats-officedocument.presentationml.template"},
            {"ppsx","application/vnd.openxmlformats-officedocument.presentationml.slideshow"},
            {"ppam","application/vnd.ms-powerpoint.addin.macroEnabled.12"},
            {"pptm","application/vnd.ms-powerpoint.presentation.macroEnabled.12"},
            {"potm","application/vnd.ms-powerpoint.template.macroEnabled.12"},
            {"ppsm","application/vnd.ms-powerpoint.slideshow.macroEnabled.12"},
            {"ps", "application/postscript"},
            {"qt", "video/quicktime"},
            {"qti", "image/x-quicktime"},
            {"qtif", "image/x-quicktime"},
            {"ra", "audio/x-pn-realaudio"},
            {"ram", "audio/x-pn-realaudio"},
            {"ras", "image/x-cmu-raster"},
            {"rdf", "application/rdf+xml"},
            {"rgb", "image/x-rgb"},
            {"rm", "application/vnd.rn-realmedia"},
            {"roff", "application/x-troff"},
            {"rtf", "text/rtf"},
            {"rtx", "text/richtext"},
            {"sgm", "text/sgml"},
            {"sgml", "text/sgml"},
            {"sh", "application/x-sh"},
            {"shar", "application/x-shar"},
            {"silo", "model/mesh"},
            {"sit", "application/x-stuffit"},
            {"skd", "application/x-koan"},
            {"skm", "application/x-koan"},
            {"skp", "application/x-koan"},
            {"skt", "application/x-koan"},
            {"smi", "application/smil"},
            {"smil", "application/smil"},
            {"snd", "audio/basic"},
            {"so", "application/octet-stream"},
            {"spl", "application/x-futuresplash"},
            {"src", "application/x-wais-source"},
            {"sv4cpio", "application/x-sv4cpio"},
            {"sv4crc", "application/x-sv4crc"},
            {"svg", "image/svg+xml"},
            {"swf", "application/x-shockwave-flash"},
            {"t", "application/x-troff"},
            {"tar", "application/x-tar"},
            {"tcl", "application/x-tcl"},
            {"tex", "application/x-tex"},
            {"texi", "application/x-texinfo"},
            {"texinfo", "application/x-texinfo"},
            {"tif", "image/tiff"},
            {"tiff", "image/tiff"},
            {"tr", "application/x-troff"},
            {"tsv", "text/tab-separated-values"},
            {"txt", "text/plain"},
            {"ustar", "application/x-ustar"},
            {"vcd", "application/x-cdlink"},
            {"vrml", "model/vrml"},
            {"vxml", "application/voicexml+xml"},
            {"wav", "audio/x-wav"},
            {"wbmp", "image/vnd.wap.wbmp"},
            {"wbmxl", "application/vnd.wap.wbxml"},
            {"wml", "text/vnd.wap.wml"},
            {"wmlc", "application/vnd.wap.wmlc"},
            {"wmls", "text/vnd.wap.wmlscript"},
            {"wmlsc", "application/vnd.wap.wmlscriptc"},
            {"wrl", "model/vrml"},
            {"xbm", "image/x-xbitmap"},
            {"xht", "application/xhtml+xml"},
            {"xhtml", "application/xhtml+xml"},
            {"xls", "application/vnd.ms-excel"},                                                
            {"xml", "application/xml"},
            {"xpm", "image/x-xpixmap"},
            {"xsl", "application/xml"},
            {"xlsx","application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"},
            {"xltx","application/vnd.openxmlformats-officedocument.spreadsheetml.template"},
            {"xlsm","application/vnd.ms-excel.sheet.macroEnabled.12"},
            {"xltm","application/vnd.ms-excel.template.macroEnabled.12"},
            {"xlam","application/vnd.ms-excel.addin.macroEnabled.12"},
            {"xlsb","application/vnd.ms-excel.sheet.binary.macroEnabled.12"},
            {"xslt", "application/xslt+xml"},
            {"xul", "application/vnd.mozilla.xul+xml"},
            {"xwd", "image/x-xwindowdump"},
            {"xyz", "chemical/x-xyz"},
            {"zip", "application/zip"}
        };
    }
}

3
Đừng quên Thử bắt xung quanh sổ đăng ký - bạn sẽ không được phép truy cập vào chế độ giới hạn, đó là trường hợp có vai trò Azure Web trong độ tin cậy hạn chế hoặc mọi máy chủ khác có độ tin cậy giới hạn.
Ognyan Dimitrov

2

Tôi thấy cái này hữu ích. Dành cho nhà phát triển VB.NET:

    Public Shared Function GetFromFileName(ByVal fileName As String) As String
        Return GetFromExtension(Path.GetExtension(fileName).Remove(0, 1))
    End Function

    Public Shared Function GetFromExtension(ByVal extension As String) As String
        If extension.StartsWith("."c) Then
            extension = extension.Remove(0, 1)
        End If

        If MIMETypesDictionary.ContainsKey(extension) Then
            Return MIMETypesDictionary(extension)
        End If

        Return "unknown/unknown"
    End Function

    Private Shared ReadOnly MIMETypesDictionary As New Dictionary(Of String, String)() From { _
         {"ai", "application/postscript"}, _
         {"aif", "audio/x-aiff"}, _
         {"aifc", "audio/x-aiff"}, _
         {"aiff", "audio/x-aiff"}, _
         {"asc", "text/plain"}, _
         {"atom", "application/atom+xml"}, _
         {"au", "audio/basic"}, _
         {"avi", "video/x-msvideo"}, _
         {"bcpio", "application/x-bcpio"}, _
         {"bin", "application/octet-stream"}, _
         {"bmp", "image/bmp"}, _
         {"cdf", "application/x-netcdf"}, _
         {"cgm", "image/cgm"}, _
         {"class", "application/octet-stream"}, _
         {"cpio", "application/x-cpio"}, _
         {"cpt", "application/mac-compactpro"}, _
         {"csh", "application/x-csh"}, _
         {"css", "text/css"}, _
         {"dcr", "application/x-director"}, _
         {"dif", "video/x-dv"}, _
         {"dir", "application/x-director"}, _
         {"djv", "image/vnd.djvu"}, _
         {"djvu", "image/vnd.djvu"}, _
         {"dll", "application/octet-stream"}, _
         {"dmg", "application/octet-stream"}, _
         {"dms", "application/octet-stream"}, _
         {"doc", "application/msword"}, _
         {"dtd", "application/xml-dtd"}, _
         {"dv", "video/x-dv"}, _
         {"dvi", "application/x-dvi"}, _
         {"dxr", "application/x-director"}, _
         {"eps", "application/postscript"}, _
         {"etx", "text/x-setext"}, _
         {"exe", "application/octet-stream"}, _
         {"ez", "application/andrew-inset"}, _
         {"gif", "image/gif"}, _
         {"gram", "application/srgs"}, _
         {"grxml", "application/srgs+xml"}, _
         {"gtar", "application/x-gtar"}, _
         {"hdf", "application/x-hdf"}, _
         {"hqx", "application/mac-binhex40"}, _
         {"htm", "text/html"}, _
         {"html", "text/html"}, _
         {"ice", "x-conference/x-cooltalk"}, _
         {"ico", "image/x-icon"}, _
         {"ics", "text/calendar"}, _
         {"ief", "image/ief"}, _
         {"ifb", "text/calendar"}, _
         {"iges", "model/iges"}, _
         {"igs", "model/iges"}, _
         {"jnlp", "application/x-java-jnlp-file"}, _
         {"jp2", "image/jp2"}, _
         {"jpe", "image/jpeg"}, _
         {"jpeg", "image/jpeg"}, _
         {"jpg", "image/jpeg"}, _
         {"js", "application/x-javascript"}, _
         {"kar", "audio/midi"}, _
         {"latex", "application/x-latex"}, _
         {"lha", "application/octet-stream"}, _
         {"lzh", "application/octet-stream"}, _
         {"m3u", "audio/x-mpegurl"}, _
         {"m4a", "audio/mp4a-latm"}, _
         {"m4b", "audio/mp4a-latm"}, _
         {"m4p", "audio/mp4a-latm"}, _
         {"m4u", "video/vnd.mpegurl"}, _
         {"m4v", "video/x-m4v"}, _
         {"mac", "image/x-macpaint"}, _
         {"man", "application/x-troff-man"}, _
         {"mathml", "application/mathml+xml"}, _
         {"me", "application/x-troff-me"}, _
         {"mesh", "model/mesh"}, _
         {"mid", "audio/midi"}, _
         {"midi", "audio/midi"}, _
         {"mif", "application/vnd.mif"}, _
         {"mov", "video/quicktime"}, _
         {"movie", "video/x-sgi-movie"}, _
         {"mp2", "audio/mpeg"}, _
         {"mp3", "audio/mpeg"}, _
         {"mp4", "video/mp4"}, _
         {"mpe", "video/mpeg"}, _
         {"mpeg", "video/mpeg"}, _
         {"mpg", "video/mpeg"}, _
         {"mpga", "audio/mpeg"}, _
         {"ms", "application/x-troff-ms"}, _
         {"msh", "model/mesh"}, _
         {"mxu", "video/vnd.mpegurl"}, _
         {"nc", "application/x-netcdf"}, _
         {"oda", "application/oda"}, _
         {"ogg", "application/ogg"}, _
         {"pbm", "image/x-portable-bitmap"}, _
         {"pct", "image/pict"}, _
         {"pdb", "chemical/x-pdb"}, _
         {"pdf", "application/pdf"}, _
         {"pgm", "image/x-portable-graymap"}, _
         {"pgn", "application/x-chess-pgn"}, _
         {"pic", "image/pict"}, _
         {"pict", "image/pict"}, _
         {"png", "image/png"}, _
         {"pnm", "image/x-portable-anymap"}, _
         {"pnt", "image/x-macpaint"}, _
         {"pntg", "image/x-macpaint"}, _
         {"ppm", "image/x-portable-pixmap"}, _
         {"ppt", "application/vnd.ms-powerpoint"}, _
         {"ps", "application/postscript"}, _
         {"qt", "video/quicktime"}, _
         {"qti", "image/x-quicktime"}, _
         {"qtif", "image/x-quicktime"}, _
         {"ra", "audio/x-pn-realaudio"}, _
         {"ram", "audio/x-pn-realaudio"}, _
         {"ras", "image/x-cmu-raster"}, _
         {"rdf", "application/rdf+xml"}, _
         {"rgb", "image/x-rgb"}, _
         {"rm", "application/vnd.rn-realmedia"}, _
         {"roff", "application/x-troff"}, _
         {"rtf", "text/rtf"}, _
         {"rtx", "text/richtext"}, _
         {"sgm", "text/sgml"}, _
         {"sgml", "text/sgml"}, _
         {"sh", "application/x-sh"}, _
         {"shar", "application/x-shar"}, _
         {"silo", "model/mesh"}, _
         {"sit", "application/x-stuffit"}, _
         {"skd", "application/x-koan"}, _
         {"skm", "application/x-koan"}, _
         {"skp", "application/x-koan"}, _
         {"skt", "application/x-koan"}, _
         {"smi", "application/smil"}, _
         {"smil", "application/smil"}, _
         {"snd", "audio/basic"}, _
         {"so", "application/octet-stream"}, _
         {"spl", "application/x-futuresplash"}, _
         {"src", "application/x-wais-source"}, _
         {"sv4cpio", "application/x-sv4cpio"}, _
         {"sv4crc", "application/x-sv4crc"}, _
         {"svg", "image/svg+xml"}, _
         {"swf", "application/x-shockwave-flash"}, _
         {"t", "application/x-troff"}, _
         {"tar", "application/x-tar"}, _
         {"tcl", "application/x-tcl"}, _
         {"tex", "application/x-tex"}, _
         {"texi", "application/x-texinfo"}, _
         {"texinfo", "application/x-texinfo"}, _
         {"tif", "image/tiff"}, _
         {"tiff", "image/tiff"}, _
         {"tr", "application/x-troff"}, _
         {"tsv", "text/tab-separated-values"}, _
         {"txt", "text/plain"}, _
         {"ustar", "application/x-ustar"}, _
         {"vcd", "application/x-cdlink"}, _
         {"vrml", "model/vrml"}, _
         {"vxml", "application/voicexml+xml"}, _
         {"wav", "audio/x-wav"}, _
         {"wbmp", "image/vnd.wap.wbmp"}, _
         {"wbmxl", "application/vnd.wap.wbxml"}, _
         {"wml", "text/vnd.wap.wml"}, _
         {"wmlc", "application/vnd.wap.wmlc"}, _
         {"wmls", "text/vnd.wap.wmlscript"}, _
         {"wmlsc", "application/vnd.wap.wmlscriptc"}, _
         {"wrl", "model/vrml"}, _
         {"xbm", "image/x-xbitmap"}, _
         {"xht", "application/xhtml+xml"}, _
         {"xhtml", "application/xhtml+xml"}, _
         {"xls", "application/vnd.ms-excel"}, _
         {"xml", "application/xml"}, _
         {"xpm", "image/x-xpixmap"}, _
         {"xsl", "application/xml"}, _
         {"xslt", "application/xslt+xml"}, _
         {"xul", "application/vnd.mozilla.xul+xml"}, _
         {"xwd", "image/x-xwindowdump"}, _
         {"xyz", "chemical/x-xyz"}, _
         {"zip", "application/zip"} _
        }

4
có vẻ như đó có thể là một danh sách cũ ... không .docx, .xlsx, v.v.
JoelFan

Có một danh sách trực tuyến ở đâu đó? Danh sách trên có vẻ đầy đủ hơn một chút và tìm thấy một số cái còn thiếu ở đây: stackoverflow.com/questions/4212861/iêu - nhưng có vẻ như cần có một dịch vụ web ở đâu đó mà bạn chỉ cần gửi tên tệp và một số byte cũng có thể đoán đúng nhất và tìm ra phần còn lại ...
BrainSlugs83

Tôi sẽ sử dụng cấu hình cho việc này, vì vậy tôi có thể chọn loại mime tôi cần và sửa đổi chúng cho phù hợp, mà không thay đổi một dòng mã
Ivaylo Slavov

2

Tôi đã gặp một vấn đề tương tự và cuối cùng đã chọn cho mình hương vị của giải pháp Kirk Baucom, được tìm thấy ở đây .

Dường như với tôi rằng đây là cơ hội để ai đó viết một dịch vụ tra cứu trực tuyến.

Dù sao, hy vọng nó sẽ giúp.


2

Nếu ai đó đã sẵn sàng, họ có thể chuyển mô-đun perl tuyệt vời File :: Type sang .NET. Trong mã là một tập hợp các số ma thuật tiêu đề tìm kiếm cho từng loại tệp hoặc biểu thức khớp chính xác.

Đây là một thư viện phát hiện loại tệp .NET http://filetypedetective.codeplex.com/ nhưng nó chỉ phát hiện một số lượng nhỏ các tệp tại thời điểm này.


2

Câu trả lời này là bản sao câu trả lời của tác giả (Richard Gourlay), nhưng đã được cải thiện để giải quyết các vấn đề trên IIS 8 / win2012 (trong đó chức năng sẽ khiến nhóm ứng dụng bị sập), dựa trên nhận xét của Rohland chỉ vào http://www.pinvoke.net /default.aspx/urlmon.findmimefromdata

using System.Runtime.InteropServices;

...

public static string GetMimeFromFile(string filename)
{

    if (!File.Exists(filename))
        throw new FileNotFoundException(filename + " not found");

    const int maxContent = 256;

    var buffer = new byte[maxContent];
    using (var fs = new FileStream(filename, FileMode.Open))
    {
        if (fs.Length >= maxContent)
            fs.Read(buffer, 0, maxContent);
        else
            fs.Read(buffer, 0, (int) fs.Length);
    }

    var mimeTypePtr = IntPtr.Zero;
    try
    {
        var result = FindMimeFromData(IntPtr.Zero, null, buffer, maxContent, null, 0, out mimeTypePtr, 0);
        if (result != 0)
        {
            Marshal.FreeCoTaskMem(mimeTypePtr);
            throw Marshal.GetExceptionForHR(result);
        }

        var mime = Marshal.PtrToStringUni(mimeTypePtr);
        Marshal.FreeCoTaskMem(mimeTypePtr);
        return mime;
    }
    catch (Exception e)
    {
        if (mimeTypePtr != IntPtr.Zero)
        {
            Marshal.FreeCoTaskMem(mimeTypePtr);
        }
        return "unknown/unknown";
    }
}

[DllImport("urlmon.dll", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = false)]
private static extern int FindMimeFromData(IntPtr pBC,
    [MarshalAs(UnmanagedType.LPWStr)] string pwzUrl,
    [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.I1, SizeParamIndex = 3)] byte[] pBuffer,
    int cbSize,
    [MarshalAs(UnmanagedType.LPWStr)] string pwzMimeProposed,
    int dwMimeFlags,
    out IntPtr ppwzMimeOut,
    int dwReserved);

Nice C + P có thể trả lời. Chrs
Nhà phát triển Meme

2

@Steve Morgan và @Richard Gourlay đây là một giải pháp tuyệt vời, cảm ơn bạn vì điều đó. Một nhược điểm nhỏ là khi số byte trong một tệp là 255 hoặc thấp hơn, loại mime đôi khi sẽ mang lại "application / octet-stream", hơi không chính xác cho các tệp sẽ mang lại "text / plain". Tôi đã cập nhật phương pháp ban đầu của bạn để giải thích cho tình huống này như sau:

Nếu số byte trong tệp nhỏ hơn hoặc bằng 255 và loại mime được suy ra là "application / octet-stream", thì hãy tạo một mảng byte mới bao gồm các byte tệp gốc được lặp lại n lần cho đến khi tổng số của byte là> = 256. Sau đó kiểm tra lại loại mime trên mảng byte mới đó.

Phương pháp sửa đổi:

Imports System.Runtime.InteropServices

<DllImport("urlmon.dll", CharSet:=CharSet.Auto)> _
Private Shared Function FindMimeFromData(pBC As System.UInt32, <MarshalAs(UnmanagedType.LPStr)> pwzUrl As System.String, <MarshalAs(UnmanagedType.LPArray)> pBuffer As Byte(), cbSize As System.UInt32, <MarshalAs(UnmanagedType.LPStr)> pwzMimeProposed As System.String, dwMimeFlags As System.UInt32, _
ByRef ppwzMimeOut As System.UInt32, dwReserverd As System.UInt32) As System.UInt32
End Function
Private Function GetMimeType(ByVal f As FileInfo) As String
    'See http://stackoverflow.com/questions/58510/using-net-how-can-you-find-the-mime-type-of-a-file-based-on-the-file-signature
    Dim returnValue As String = ""
    Dim fileStream As FileStream = Nothing
    Dim fileStreamLength As Long = 0
    Dim fileStreamIsLessThanBByteSize As Boolean = False

    Const byteSize As Integer = 255
    Const bbyteSize As Integer = byteSize + 1

    Const ambiguousMimeType As String = "application/octet-stream"
    Const unknownMimeType As String = "unknown/unknown"

    Dim buffer As Byte() = New Byte(byteSize) {}
    Dim fnGetMimeTypeValue As New Func(Of Byte(), Integer, String)(
        Function(_buffer As Byte(), _bbyteSize As Integer) As String
            Dim _returnValue As String = ""
            Dim mimeType As UInt32 = 0
            FindMimeFromData(0, Nothing, _buffer, _bbyteSize, Nothing, 0, mimeType, 0)
            Dim mimeTypePtr As IntPtr = New IntPtr(mimeType)
            _returnValue = Marshal.PtrToStringUni(mimeTypePtr)
            Marshal.FreeCoTaskMem(mimeTypePtr)
            Return _returnValue
        End Function)

    If (f.Exists()) Then
        Try
            fileStream = New FileStream(f.FullName(), FileMode.Open, FileAccess.Read, FileShare.ReadWrite)
            fileStreamLength = fileStream.Length()

            If (fileStreamLength >= bbyteSize) Then
                fileStream.Read(buffer, 0, bbyteSize)
            Else
                fileStreamIsLessThanBByteSize = True
                fileStream.Read(buffer, 0, CInt(fileStreamLength))
            End If

            returnValue = fnGetMimeTypeValue(buffer, bbyteSize)

            If (returnValue.Equals(ambiguousMimeType, StringComparison.OrdinalIgnoreCase) AndAlso fileStreamIsLessThanBByteSize AndAlso fileStreamLength > 0) Then
                'Duplicate the stream content until the stream length is >= bbyteSize to get a more deterministic mime type analysis.
                Dim currentBuffer As Byte() = buffer.Take(fileStreamLength).ToArray()
                Dim repeatCount As Integer = Math.Floor((bbyteSize / fileStreamLength) + 1)
                Dim bBufferList As List(Of Byte) = New List(Of Byte)
                While (repeatCount > 0)
                    bBufferList.AddRange(currentBuffer)
                    repeatCount -= 1
                End While
                Dim bbuffer As Byte() = bBufferList.Take(bbyteSize).ToArray()
                returnValue = fnGetMimeTypeValue(bbuffer, bbyteSize)
            End If
        Catch ex As Exception
            returnValue = unknownMimeType
        Finally
            If (fileStream IsNot Nothing) Then fileStream.Close()
        End Try
    End If
    Return returnValue
End Function

Đây là vấn đề tôi gặp phải và ý tưởng của bạn thật tuyệt vời, để sao chép các byte. Tôi đã phải thực hiện nó trong c #, nhưng bằng cách sử dụng độ dài của tệp và bộ đệm có các byte đầu tiên của tệp, tôi có thể lặp lại tất cả các byte bị thiếu và sao chép các byte trong mảng để lặp lại tệp (i chỉ sao chép byte từ idx có độ dài tệp trước đó trong mảng).
Richard Duerr

1

IIS 7 trở lên

Sử dụng mã này, nhưng bạn cần phải là quản trị viên trên máy chủ

public bool CheckMimeMapExtension(string fileExtension)
        {
            try
            {

                using (
                ServerManager serverManager = new ServerManager())
                {   
                    // connects to default app.config
                    var config = serverManager.GetApplicationHostConfiguration();
                    var staticContent = config.GetSection("system.webServer/staticContent");
                    var mimeMap = staticContent.GetCollection();

                    foreach (var mimeType in mimeMap)
                    {

                        if (((String)mimeType["fileExtension"]).Equals(fileExtension, StringComparison.OrdinalIgnoreCase))
                            return true;

                    }

                }
                return false;
            }
            catch (Exception ex)
            { 
                Console.WriteLine("An exception has occurred: \n{0}", ex.Message);
                Console.Read();
            }

            return false;

        }

Còn giả mạo thì sao?
TS

0

Khi làm việc với vai trò Windows Azure Web hoặc bất kỳ máy chủ nào khác chạy ứng dụng của bạn trong Limited Trust, đừng quên rằng bạn sẽ không được phép truy cập vào sổ đăng ký hoặc mã không được quản lý. Phương pháp lai - kết hợp từ điển try-Catch-for-registry và trong bộ nhớ trông giống như một giải pháp tốt có một chút của mọi thứ.

Tôi sử dụng mã này để làm điều đó:

public class DefaultMimeResolver : IMimeResolver
{
    private readonly IFileRepository _fileRepository;

    public DefaultMimeResolver(IFileRepository fileRepository)
    {
        _fileRepository = fileRepository;
    }

    [DllImport(@"urlmon.dll", CharSet = CharSet.Auto)]
    private static extern System.UInt32 FindMimeFromData(
        System.UInt32 pBC, [MarshalAs(UnmanagedType.LPStr)] System.String pwzUrl,
         [MarshalAs(UnmanagedType.LPArray)] byte[] pBuffer,
         System.UInt32 cbSize,
         [MarshalAs(UnmanagedType.LPStr)] System.String pwzMimeProposed,
         System.UInt32 dwMimeFlags,
         out System.UInt32 ppwzMimeOut,
         System.UInt32 dwReserverd);


    public string GetMimeTypeFromFileExtension(string fileExtension)
    {
        if (string.IsNullOrEmpty(fileExtension))
        {
            throw new ArgumentNullException("fileExtension");
        }

        string mimeType = GetMimeTypeFromList(fileExtension);

        if (String.IsNullOrEmpty(mimeType))
        {
            mimeType = GetMimeTypeFromRegistry(fileExtension);
        }

        return mimeType;
    }

    public string GetMimeTypeFromFile(string filePath)
    {
        if (string.IsNullOrEmpty(filePath))
        {
            throw new ArgumentNullException("filePath");
        }

        if (!File.Exists(filePath))
        {
            throw new FileNotFoundException("File not found : ", filePath);
        }

        string mimeType = GetMimeTypeFromList(Path.GetExtension(filePath).ToLower());

        if (String.IsNullOrEmpty(mimeType))
        {
            mimeType = GetMimeTypeFromRegistry(Path.GetExtension(filePath).ToLower());

            if (String.IsNullOrEmpty(mimeType))
            {
                mimeType = GetMimeTypeFromFileInternal(filePath);
            }
        }

        return mimeType;
    }

    private string GetMimeTypeFromList(string fileExtension)
    {
        string mimeType = null;

        if (fileExtension.StartsWith("."))
        {
            fileExtension = fileExtension.TrimStart('.');
        }

        if (!String.IsNullOrEmpty(fileExtension) && _mimeTypes.ContainsKey(fileExtension))
        {
            mimeType = _mimeTypes[fileExtension];
        }

        return mimeType;
    }

    private string GetMimeTypeFromRegistry(string fileExtension)
    {
        string mimeType = null;
        try
        {
            RegistryKey key = Registry.ClassesRoot.OpenSubKey(fileExtension);

            if (key != null && key.GetValue("Content Type") != null)
            {
                mimeType = key.GetValue("Content Type").ToString();
            }
        }
        catch (Exception)
        {
            // Empty. When this code is running in limited mode accessing registry is not allowed.
        }

        return mimeType;
    }

    private string GetMimeTypeFromFileInternal(string filePath)
    {
        string mimeType = null;

        if (!File.Exists(filePath))
        {
            return null;
        }

        byte[] byteBuffer = new byte[256];

        using (FileStream fileStream = _fileRepository.Get(filePath))
        {
            if (fileStream.Length >= 256)
            {
                fileStream.Read(byteBuffer, 0, 256);
            }
            else
            {
                fileStream.Read(byteBuffer, 0, (int)fileStream.Length);
            }
        }

        try
        {
            UInt32 MimeTypeNum;

            FindMimeFromData(0, null, byteBuffer, 256, null, 0, out MimeTypeNum, 0);

            IntPtr mimeTypePtr = new IntPtr(MimeTypeNum);
            string mimeTypeFromFile = Marshal.PtrToStringUni(mimeTypePtr);

            Marshal.FreeCoTaskMem(mimeTypePtr);

            if (!String.IsNullOrEmpty(mimeTypeFromFile) && mimeTypeFromFile != "text/plain" && mimeTypeFromFile != "application/octet-stream")
            {
                mimeType = mimeTypeFromFile;
            }
        }
        catch
        {
            // Empty. 
        }

        return mimeType;
    }

    private readonly Dictionary<string, string> _mimeTypes = new Dictionary<string, string>
        {
            {"ai", "application/postscript"},
            {"aif", "audio/x-aiff"},
            {"aifc", "audio/x-aiff"},
            {"aiff", "audio/x-aiff"},
            {"asc", "text/plain"},
            {"atom", "application/atom+xml"},
            {"au", "audio/basic"},
            {"avi", "video/x-msvideo"},
            {"bcpio", "application/x-bcpio"},
            {"bin", "application/octet-stream"},
            {"bmp", "image/bmp"},
            {"cdf", "application/x-netcdf"},
            {"cgm", "image/cgm"},
            {"class", "application/octet-stream"},
            {"cpio", "application/x-cpio"},
            {"cpt", "application/mac-compactpro"},
            {"csh", "application/x-csh"},
            {"css", "text/css"},
            {"dcr", "application/x-director"},
            {"dif", "video/x-dv"},
            {"dir", "application/x-director"},
            {"djv", "image/vnd.djvu"},
            {"djvu", "image/vnd.djvu"},
            {"dll", "application/octet-stream"},
            {"dmg", "application/octet-stream"},
            {"dms", "application/octet-stream"},
            {"doc", "application/msword"},
            {"docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document"},
            {"dotx", "application/vnd.openxmlformats-officedocument.wordprocessingml.template"},
            {"docm", "application/vnd.ms-word.document.macroEnabled.12"},
            {"dotm", "application/vnd.ms-word.template.macroEnabled.12"},
            {"dtd", "application/xml-dtd"},
            {"dv", "video/x-dv"},
            {"dvi", "application/x-dvi"},
            {"dxr", "application/x-director"},
            {"eps", "application/postscript"},
            {"etx", "text/x-setext"},
            {"exe", "application/octet-stream"},
            {"ez", "application/andrew-inset"},
            {"gif", "image/gif"},
            {"gram", "application/srgs"},
            {"grxml", "application/srgs+xml"},
            {"gtar", "application/x-gtar"},
            {"hdf", "application/x-hdf"},
            {"hqx", "application/mac-binhex40"},
            {"htc", "text/x-component"},
            {"htm", "text/html"},
            {"html", "text/html"},
            {"ice", "x-conference/x-cooltalk"},
            {"ico", "image/x-icon"},
            {"ics", "text/calendar"},
            {"ief", "image/ief"},
            {"ifb", "text/calendar"},
            {"iges", "model/iges"},
            {"igs", "model/iges"},
            {"jnlp", "application/x-java-jnlp-file"},
            {"jp2", "image/jp2"},
            {"jpe", "image/jpeg"},
            {"jpeg", "image/jpeg"},
            {"jpg", "image/jpeg"},
            {"js", "application/x-javascript"},
            {"kar", "audio/midi"},
            {"latex", "application/x-latex"},
            {"lha", "application/octet-stream"},
            {"lzh", "application/octet-stream"},
            {"m3u", "audio/x-mpegurl"},
            {"m4a", "audio/mp4a-latm"},
            {"m4b", "audio/mp4a-latm"},
            {"m4p", "audio/mp4a-latm"},
            {"m4u", "video/vnd.mpegurl"},
            {"m4v", "video/x-m4v"},
            {"mac", "image/x-macpaint"},
            {"man", "application/x-troff-man"},
            {"mathml", "application/mathml+xml"},
            {"me", "application/x-troff-me"},
            {"mesh", "model/mesh"},
            {"mid", "audio/midi"},
            {"midi", "audio/midi"},
            {"mif", "application/vnd.mif"},
            {"mov", "video/quicktime"},
            {"movie", "video/x-sgi-movie"},
            {"mp2", "audio/mpeg"},
            {"mp3", "audio/mpeg"},
            {"mp4", "video/mp4"},
            {"mpe", "video/mpeg"},
            {"mpeg", "video/mpeg"},
            {"mpg", "video/mpeg"},
            {"mpga", "audio/mpeg"},
            {"ms", "application/x-troff-ms"},
            {"msh", "model/mesh"},
            {"mxu", "video/vnd.mpegurl"},
            {"nc", "application/x-netcdf"},
            {"oda", "application/oda"},
            {"ogg", "application/ogg"},
            {"pbm", "image/x-portable-bitmap"},
            {"pct", "image/pict"},
            {"pdb", "chemical/x-pdb"},
            {"pdf", "application/pdf"},
            {"pgm", "image/x-portable-graymap"},
            {"pgn", "application/x-chess-pgn"},
            {"pic", "image/pict"},
            {"pict", "image/pict"},
            {"png", "image/png"},
            {"pnm", "image/x-portable-anymap"},
            {"pnt", "image/x-macpaint"},
            {"pntg", "image/x-macpaint"},
            {"ppm", "image/x-portable-pixmap"},
            {"ppt", "application/vnd.ms-powerpoint"},
            {"pptx", "application/vnd.openxmlformats-officedocument.presentationml.presentation"},
            {"potx", "application/vnd.openxmlformats-officedocument.presentationml.template"},
            {"ppsx", "application/vnd.openxmlformats-officedocument.presentationml.slideshow"},
            {"ppam", "application/vnd.ms-powerpoint.addin.macroEnabled.12"},
            {"pptm", "application/vnd.ms-powerpoint.presentation.macroEnabled.12"},
            {"potm", "application/vnd.ms-powerpoint.template.macroEnabled.12"},
            {"ppsm", "application/vnd.ms-powerpoint.slideshow.macroEnabled.12"},
            {"ps", "application/postscript"},
            {"qt", "video/quicktime"},
            {"qti", "image/x-quicktime"},
            {"qtif", "image/x-quicktime"},
            {"ra", "audio/x-pn-realaudio"},
            {"ram", "audio/x-pn-realaudio"},
            {"ras", "image/x-cmu-raster"},
            {"rdf", "application/rdf+xml"},
            {"rgb", "image/x-rgb"},
            {"rm", "application/vnd.rn-realmedia"},
            {"roff", "application/x-troff"},
            {"rtf", "text/rtf"},
            {"rtx", "text/richtext"},
            {"sgm", "text/sgml"},
            {"sgml", "text/sgml"},
            {"sh", "application/x-sh"},
            {"shar", "application/x-shar"},
            {"silo", "model/mesh"},
            {"sit", "application/x-stuffit"},
            {"skd", "application/x-koan"},
            {"skm", "application/x-koan"},
            {"skp", "application/x-koan"},
            {"skt", "application/x-koan"},
            {"smi", "application/smil"},
            {"smil", "application/smil"},
            {"snd", "audio/basic"},
            {"so", "application/octet-stream"},
            {"spl", "application/x-futuresplash"},
            {"src", "application/x-wais-source"},
            {"sv4cpio", "application/x-sv4cpio"},
            {"sv4crc", "application/x-sv4crc"},
            {"svg", "image/svg+xml"},
            {"swf", "application/x-shockwave-flash"},
            {"t", "application/x-troff"},
            {"tar", "application/x-tar"},
            {"tcl", "application/x-tcl"},
            {"tex", "application/x-tex"},
            {"texi", "application/x-texinfo"},
            {"texinfo", "application/x-texinfo"},
            {"tif", "image/tiff"},
            {"tiff", "image/tiff"},
            {"tr", "application/x-troff"},
            {"tsv", "text/tab-separated-values"},
            {"txt", "text/plain"},
            {"ustar", "application/x-ustar"},
            {"vcd", "application/x-cdlink"},
            {"vrml", "model/vrml"},
            {"vxml", "application/voicexml+xml"},
            {"wav", "audio/x-wav"},
            {"wbmp", "image/vnd.wap.wbmp"},
            {"wbmxl", "application/vnd.wap.wbxml"},
            {"wml", "text/vnd.wap.wml"},
            {"wmlc", "application/vnd.wap.wmlc"},
            {"wmls", "text/vnd.wap.wmlscript"},
            {"wmlsc", "application/vnd.wap.wmlscriptc"},
            {"wrl", "model/vrml"},
            {"xbm", "image/x-xbitmap"},
            {"xht", "application/xhtml+xml"},
            {"xhtml", "application/xhtml+xml"},
            {"xls", "application/vnd.ms-excel"},
            {"xml", "application/xml"},
            {"xpm", "image/x-xpixmap"},
            {"xsl", "application/xml"},
            {"xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"},
            {"xltx", "application/vnd.openxmlformats-officedocument.spreadsheetml.template"},
            {"xlsm", "application/vnd.ms-excel.sheet.macroEnabled.12"},
            {"xltm", "application/vnd.ms-excel.template.macroEnabled.12"},
            {"xlam", "application/vnd.ms-excel.addin.macroEnabled.12"},
            {"xlsb", "application/vnd.ms-excel.sheet.binary.macroEnabled.12"},
            {"xslt", "application/xslt+xml"},
            {"xul", "application/vnd.mozilla.xul+xml"},
            {"xwd", "image/x-xwindowdump"},
            {"xyz", "chemical/x-xyz"},
            {"zip", "application/zip"}
        };
}

Tôi sẽ thành thật đánh giá cao bất kỳ bình luận nào về việc bỏ phiếu xuống - tôi thực sự muốn tìm hiểu về bất kỳ hành vi sai trái tiềm năng nào của mã này.
Ognyan Dimitrov

Tôi không thấy bất kỳ khối bắt thử nào trong mã của bạn khi bạn sử dụng GetMimeTypeFromFileI Internalal. Vì vậy, có vẻ như mặc định bạn chỉ cần kiểm tra phần mở rộng tệp, điều này không thực sự hữu ích nếu bạn không chắc chắn, những gì thực sự bên trong tệp. Và tôi vẫn không thể nhận được, liệu GetMimeTypeFromFileI Internalal có hoạt động trong Azure với Limited Trust không? Nếu không thì tại sao nó vẫn còn trong mã?
Alexander Skogorev

1
Trong trường hợp bối cảnh thực thi bị giới hạn, bạn có thể giới hạn mã chỉ sử dụng danh sách. Vâng, có nhiều phần mở rộng hơn thế, nhưng chỉ có nhà phát triển biết ngữ cảnh của ứng dụng và có thể thêm nhiều hơn vào danh sách. Và một thử bắt là bổ sung tốt đó là chắc chắn.
Ognyan Dimitrov

0

Tôi đã kết thúc bằng Winista MimeDetector từ Netomatix. Các nguồn có thể được tải xuống miễn phí sau khi bạn tạo một tài khoản: http://www.netomatix.com/ Products / DocumentQuản lý / MimeDetector.aspx

MimeTypes g_MimeTypes = new MimeTypes("mime-types.xml");
sbyte [] fileData = null;

using (System.IO.FileStream srcFile = new System.IO.FileStream(strFile, System.IO.FileMode.Open))
{
    byte [] data = new byte[srcFile.Length];
    srcFile.Read(data, 0, (Int32)srcFile.Length);
    fileData = Winista.Mime.SupportUtil.ToSByteArray(data);
}

MimeType oMimeType = g_MimeTypes.GetMimeType(fileData);

Đây là một phần của một câu hỏi khác được trả lời ở đây: Thay thế cho phương pháp FindMimeFromData trong Urlmon.dll có một loại MIME hơn Giải pháp tốt nhất cho vấn đề này theo ý kiến ​​của tôi.


0

Tôi đã tìm thấy một số vấn đề khi chạy mã này:

UInt32 mimetype;
FindMimeFromData(0, null, buffer, 256, null, 0, out mimetype, 0);

Nếu bạn cố chạy nó với x64 / Win10, bạn sẽ nhận được

AccessViolationException "Attempted to read or write protected memory.
This is often an indication that other memory is corrupt"

Nhờ bài đăng này, PtrToStringUni không hoạt động trong windows 10 và @xanatos

Tôi đã sửa đổi giải pháp của mình để chạy theo x64 và .NET Core 2.1:

   [DllImport("urlmon.dll", CharSet = CharSet.Unicode, ExactSpelling = true, 
    SetLastError = false)]
    static extern int FindMimeFromData(IntPtr pBC,
        [MarshalAs(UnmanagedType.LPWStr)] string pwzUrl,
        [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I1, 
        SizeParamIndex=3)]
        byte[] pBuffer,
        int cbSize,
        [MarshalAs(UnmanagedType.LPWStr)] string pwzMimeProposed,
        int dwMimeFlags,
        out IntPtr ppwzMimeOut,
        int dwReserved);

   string getMimeFromFile(byte[] fileSource)
   {
            byte[] buffer = new byte[256];
            using (Stream stream = new MemoryStream(fileSource))
            {
                if (stream.Length >= 256)
                    stream.Read(buffer, 0, 256);
                else
                    stream.Read(buffer, 0, (int)stream.Length);
            }

            try
            {
                IntPtr mimeTypePtr;
                FindMimeFromData(IntPtr.Zero, null, buffer, buffer.Length,
                    null, 0, out mimeTypePtr, 0);

                string mime = Marshal.PtrToStringUni(mimeTypePtr);
                Marshal.FreeCoTaskMem(mimeTypePtr);
                return mime;
            }
            catch (Exception ex)
            {
                return "unknown/unknown";
            }
   }

Cảm ơn


0

Xin chào Tôi đã điều chỉnh dự án Winista.MimeDetect thành lõi / khung .net với dự phòng vào urlmon.dll Được sử dụng miễn phí: gói nuget .

   //init
   var mimeTypes = new MimeTypes();

   //usage by filepath
   var mimeType1 = mimeTypes.GetMimeTypeFromFile(filePath);

mẫu mã gihub bị sai ở đây github.com/GetoXs/MimeDetect . không quá tảimimeTypes.GetMimeTypeFromFile(bytes);
TS

0

Tôi đã viết một trình xác nhận của loại mime. Vui lòng chia sẻ nó với bạn.

private readonly Dictionary<string, byte[]> _mimeTypes = new Dictionary<string, byte[]>
    {
        {"image/jpeg", new byte[] {255, 216, 255}},
        {"image/jpg", new byte[] {255, 216, 255}},
        {"image/pjpeg", new byte[] {255, 216, 255}},
        {"image/apng", new byte[] {137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68, 82}},
        {"image/png", new byte[] {137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68, 82}},
        {"image/bmp", new byte[] {66, 77}},
        {"image/gif", new byte[] {71, 73, 70, 56}},
    };

private bool ValidateMimeType(byte[] file, string contentType)
    {
        var imageType = _mimeTypes.SingleOrDefault(x => x.Key.Equals(contentType));

        return file.Take(imageType.Value.Length).SequenceEqual(imageType.Value);
    }
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.