Trình duyệt xác định kiểu mime của tệp tải lên như thế nào?


87

Tôi có một ứng dụng web mà người dùng cần tải lên tệp .zip. Ở phía máy chủ, tôi đang kiểm tra loại kịch câm của tệp được tải lên để đảm bảo rằng nó là application/x-zip-compressedhoặc application/zip.

Điều này hoạt động tốt đối với tôi trên Firefox và IE. Tuy nhiên, khi một đồng nghiệp kiểm tra nó, nó không thành công đối với anh ta trên Firefox (kiểu mime được gửi giống như " application/octet-stream") nhưng hoạt động trên Internet Explorer. Các thiết lập của chúng tôi dường như giống hệt nhau: IE8, FF 3.5.1 với tất cả các tiện ích bổ sung bị tắt, Win XP SP3, WinRAR được cài đặt dưới dạng trình xử lý tệp .zip gốc (không chắc liệu có liên quan không).

Vì vậy, câu hỏi của tôi là: Làm thế nào để trình duyệt xác định loại kịch câm để gửi?

Xin lưu ý: Tôi biết rằng loại kịch câm được gửi bởi trình duyệt và do đó, không đáng tin cậy. Tôi chỉ kiểm tra nó như một sự tiện lợi - chủ yếu là để đưa ra thông báo lỗi thân thiện hơn những thông báo bạn nhận được bằng cách cố gắng mở tệp không phải zip dưới dạng tệp zip và để tránh tải các thư viện tệp zip (có lẽ là nặng).


application / octet-stream chỉ định một tệp nhị phân. Bạn có thể lấy phần mở rộng của tệp để xem nó có phải là tệp zip hay không. Chỉ cần làm rõ, điều này có hiệu quả với bạn trên FF, nhưng không phải đồng nghiệp của bạn?
Kevin Crowell,

vâng, nó hoạt động với tôi trên cả hai trình duyệt
Kip 29/07/09

hãy nhìn vào input/@formenctypehoặc form/@enctypethuộc tính
tuxSlayer

Câu trả lời:


72

Trình duyệt Chrome

Chrome (phiên bản 38 tính đến thời điểm viết bài) có 3 cách để xác định kiểu MIME và làm như vậy theo một thứ tự nhất định. Đoạn mã dưới đây là từ tệp src/net/base/mime_util.cc, phương pháp MimeUtil::GetMimeTypeFromExtensionHelper.

// We implement the same algorithm as Mozilla for mapping a file extension to
// a mime type.  That is, we first check a hard-coded list (that cannot be
// overridden), and then if not found there, we defer to the system registry.
// Finally, we scan a secondary hard-coded list to catch types that we can
// deduce but that we also want to allow the OS to override.

Danh sách được mã hóa cứng xuất hiện sớm hơn một chút trong tệp: https://cs.chromium.org/chromium/src/net/base/mime_util.cc?l=170 ( kPrimaryMappingskSecondaryMappings).

Ví dụ: khi tải lên tệp CSV từ hệ thống Windows có cài đặt Microsoft Excel, Chrome sẽ báo cáo điều này là application/vnd.ms-excel. Điều này là do .csvkhông được chỉ định trong danh sách được mã hóa cứng đầu tiên, vì vậy trình duyệt rơi trở lại sổ đăng ký hệ thống. HKEY_CLASSES_ROOT\.csvcó một giá trị được đặt tên Content Typeapplication/vnd.ms-excel.

trình duyệt web IE

Một lần nữa sử dụng cùng một ví dụ, trình duyệt sẽ báo cáo application/vnd.ms-excel. Tôi nghĩ rằng thật hợp lý khi giả sử Internet Explorer (phiên bản 11 khi viết) sử dụng sổ đăng ký. Có thể nó cũng sử dụng một danh sách được mã hóa cứng như Chrome và Firefox, nhưng bản chất nguồn đóng của nó khiến rất khó để xác minh.

Firefox

Như đã nêu trong mã Chrome, Firefox (phiên bản 32 khi viết) hoạt động theo cách tương tự. Đoạn mã từ tệp uriloader\exthandler\nsExternalHelperAppService.cpp, phương thứcnsExternalHelperAppService::GetTypeFromExtension

// OK. We want to try the following sources of mimetype information, in this order:
// 1. defaultMimeEntries array
// 2. User-set preferences (managed by the handler service)
// 3. OS-provided information
// 4. our "extras" array
// 5. Information from plugins
// 6. The "ext-to-type-mapping" category

Các danh sách được mã hóa cứng xuất hiện sớm hơn trong tệp, ở đâu đó gần dòng 441. Bạn đang tìm kiếm defaultMimeEntriesextraMimeEntries.

Với hồ sơ hiện tại của tôi, trình duyệt sẽ báo cáo text/csvvì có mục nhập cho hồ sơ đó mimeTypes.rdf(mục 2 trong danh sách ở trên). Với hồ sơ mới, không có mục này, trình duyệt sẽ báo cáo application/vnd.ms-excel(mục 3 trong danh sách).

Tóm lược

Danh sách được mã hóa cứng trong trình duyệt khá hạn chế. Thông thường, kiểu MIME do trình duyệt gửi sẽ là kiểu được Hệ điều hành báo cáo. Và đây chính là lý do tại sao, như đã nêu trong câu hỏi, kiểu MIME được trình duyệt báo cáo là không đáng tin cậy.


1
cảm ơn! bạn có liên kết đến danh sách được mã hóa cứng trong nguồn chrome không?
Kip

@Kip vâng, tôi đã thêm một liên kết. Firefox dường như không có trình duyệt mã nguồn trực tuyến (chính thức), tôi phải tải xuống từ máy chủ FTP của họ.
user247702

Có MIME dưới dạng ms-excel cho CSV thật khó chịu, hãy tự hỏi tại sao nó không có trong danh sách được mã hóa cứng.
Kris

Nó sẽ được tốt đẹp để biết nếu có một số cập nhật trong việc phát hiện mime-type kể từ năm 2014.
Vitaly Isaev

1
@VitalyIsaev trong nháy mắt lướt qua tại các chương trình mã Chrome rằng điều này đã không thay đổi kể từ năm 2014.
user247702

12

Kip, tôi đã dành một chút thời gian để đọc RFC, MSDN và MDN. Đây là những gì tôi có thể hiểu. Khi trình duyệt gặp một tệp để tải lên, trình duyệt sẽ xem xét bộ đệm dữ liệu đầu tiên mà nó nhận được và sau đó chạy thử nghiệm trên đó. Các bài kiểm tra này cố gắng xác định xem tệp có phải là loại kịch câm đã biết hay không và nếu loại kịch câm đã biết, nó sẽ chỉ cần kiểm tra thêm nó cho loại kịch câm đã biết nào và thực hiện hành động tương ứng. Tôi nghĩ rằng IE cố gắng thực hiện điều này đầu tiên thay vì chỉ xác định loại tệp từ phần mở rộng. Trang này giải thích điều này cho IE http://msdn.microsoft.com/en-us/library/ms775147%28v=vs.85%29.aspx . Đối với firefox, những gì tôi có thể hiểu là nó cố gắng đọc thông tin tệp từ hệ thống tệp hoặc mục nhập thư mục và sau đó xác định loại tệp. Đây là liên kết cho FF https://developer.mozilla.org/en/XPCOM_Interface_Reference/nsIFile. Tôi vẫn muốn có thêm thông tin có thẩm quyền về điều này.


8

Đây có thể là hệ điều hành và có thể phụ thuộc vào trình duyệt, nhưng trên Windows, loại MIME cho một phần mở rộng tệp nhất định có thể được tìm thấy bằng cách tìm trong sổ đăng ký theo HKCR:

Ví dụ:

HKEY_CLASSES_ROOT.zip - ContentType

Để chuyển từ MIME sang phần mở rộng tệp, bạn có thể xem các phím bên dưới

HKEY_CLASSES_ROOT \ Mime \ Cơ sở dữ liệu \ Loại nội dung

Để nhận tiện ích mở rộng mặc định cho một loại MIME cụ thể.


cảm ơn. thật không may, đối với cả tôi và đồng nghiệp của tôi, điều này có vẻ đúng trong sổ đăng ký của chúng tôi. Tôi đoán đó là lý do tại sao nó hoạt động trong IE đối với anh ấy, nhưng FF đang làm cho nó khác đi bằng cách nào đó ... oh well :(
Kip 29/07/09

5

Mặc dù đây không phải là câu trả lời cho câu hỏi của bạn, nhưng nó giải quyết được vấn đề bạn đang cố gắng giải quyết. YMMV.

Như bạn đã viết, kiểu kịch câm không đáng tin cậy vì mỗi trình duyệt có cách xác định nó. Tuy nhiên, các trình duyệt gửi tên gốc (bao gồm cả phần mở rộng) của tệp. Vì vậy, cách tốt nhất để giải quyết vấn đề là kiểm tra phần mở rộng của tệp thay vì loại MIME.

Nếu bạn vẫn cần kiểu mime, bạn có thể sử dụng mime.types của apache của riêng bạn để xác định nó phía máy chủ.


1
Chăm sóc công phu? Theo kinh nghiệm của tôi, các trình duyệt luôn gửi đúng tên tệp gốc (có phần mở rộng) trong khi các loại MIME khác nhau rất nhiều. Vì vậy, có, tôi sẽ nói rằng nó đáng tin cậy hơn nhiều.
johndodo

Chính xác. Tôi muốn nói rằng người dùng cuối có thể đặt bất kỳ tiện ích mở rộng nào, bất kể loại thực tế nào, vì vậy nó không nên được tin cậy.
Djizeus

Điều đó đúng, nhưng không quan trọng nếu bạn sử dụng tiện ích mở rộng hoặc kiểu MIME - bạn không bao giờ nên tin tưởng đầu vào do người dùng cung cấp. Nhưng OP đã tuyên bố rõ ràng rằng ông ấy nhận thức được vấn đề này, vì vậy đây không phải là một phần của câu hỏi này. Btw, tôi sẽ đánh giá cao nếu bạn loại bỏ phiếu phản đối (tôi cho rằng nó đến từ bạn).
johndodo

Bạn nói đúng, đã không chú ý đến không có trong câu hỏi, xấu của tôi. Tôi có thể hủy bỏ phiếu bầu của mình nhưng bạn sẽ phải chỉnh sửa câu trả lời cho điều đó (do hệ thống thực thi) ...
Djizeus

Vâng, tôi đồng ý với johndodo. Như Stijn đã giải thích trong câu trả lời của mình ở trên, Chrome và Firefox sẽ kiểm tra phần mở rộng trước tiên. Cuối cùng thì họ cũng đang làm điều tương tự.
Jenix

0

Tôi đồng ý với johndodo, có quá nhiều biến khiến các loại kịch câm được gửi từ trình duyệt không đáng tin cậy. Tôi sẽ loại trừ các loại phụ được nhận và chỉ tập trung vào loại như 'ứng dụng'. nếu ứng dụng của bạn dựa trên php, bạn có thể dễ dàng thực hiện việc này bằng cách sử dụng hàm boom (). Ngoài ra, chỉ cần kiểm tra phần mở rộng tệp để đảm bảo rằng đó là .zip hoặc bất kỳ dạng nén nào khác mà bạn đang tìm kiếm!


0

Theo rfc1867 - Tải lên tệp dựa trên biểu mẫu trong HTML :

Mỗi phần phải được gắn nhãn với kiểu nội dung thích hợp nếu loại phương tiện được biết đến (ví dụ: suy ra từ phần mở rộng tệp hoặc thông tin nhập hệ điều hành) hoặc dưới dạng ứng dụng / octet-stream.

Vì vậy, sự hiểu biết của tôi là, application/octet-streamgiống như một blanket catch-allđịnh danh nếu không thể suy ra loại .


vâng, tôi hiểu tất cả những điều này. câu hỏi là làm thế nào để trình duyệt suy ra.
Kip

Đó là giá trị biết mặc dù, phải không? Nếu application/octet-streamlà tất cả, thì một cách tiếp cận khác sẽ là tin tưởng trình duyệt nếu nó có thể đoán được và thực hiện các bài kiểm tra phía máy chủ của riêng bạn nếu bạn nhận được application/octet-stream.
MikeBeaton
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.