The HttpPostedFile.ContentType
doesn’t catch the mime-type of the file while running, it picks up the content-type that the browser reported in payload during the request, or whatever determined this content-type that you see was the browser, ie the content detection occurs before the upload and occurs on the user’s machine.
This I say right away is not such a reliable way, because any HTTP request can be manipulated.
For example in an upload request of a valid file I made, called 2.xls, resulted in this:
POST /upload HTTP/1.1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Cache-Control: max-age=0
Connection: keep-alive
Content-Length: 27329
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryjUAtIb3hLXspUBmo
Host: localhost
Origin: http://localhost
Referer: http://localhost/form
User-Agent: Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.89 Safari/537.36 OPR/49.0.2725.47
------WebKitFormBoundaryjUAtIb3hLXspUBmo
Content-Disposition: form-data; name="file"; filename="2.xls"
Content-Type: application/vnd.ms-excel
------WebKitFormBoundaryjUAtIb3hLXspUBmo--
Now this was the result of a xls file invalid, called 3.xls, which is actually just a content text file this just foo bar
,
the result was (summarized the result to display only the relevant part):
------WebKitFormBoundarySMenF7hr3QNf4T6l
Content-Disposition: form-data; name="file"; filename="3.xls"
Content-Type: application/vnd.ms-excel
------WebKitFormBoundarySMenF7hr3QNf4T6l--
See, he accused it is application/vnd.ms-excel
, that is not what is expected.
Upload from Arqivos doc, docx, xls, xlsx, ppt, pptx appear as "application/octet-stream"?
I know that in my example appeared application/vnd.ms-excel
, but that’s the point I want to make, I’m not sure of the conditions that the upload was made, but one thing I can tell you, if you’re using an older browser, I’ve noticed that most modern browsers, even IE11, tries to do a good job to detect and pass on the most correct mime-type to a specific file type, but really has no way to guarantee.
I even looked for some package via Nuget: https://www.nuget.org/packages?q=mime+type, only that I only found those guess what by file extension, ie would not be a mime-type detection and rather a map, which would not be anything interesting, because it would install something else for something you could simply validate using something like:
using System.IO;
...
string Nome = UP_Dados.PostedFile.FileName;
if (Path.GetExtension(Nome).ToLower() == ".xls") {
//Validou
} else {
//Não validou
}
The most I could find of anything supposedly work for this is the function FindMimeFromData
, that is not native to C#, he is part of the urlmon.dll
, what I found of attempts of use were:
However when testing 3 files, the 1.xlsx
, 2.xls
and 3.xls
(fake file), I got this result:
It is important to note that the urlmon
is a part of Internet Explorer that is installed on your server, my IE is the most updated and yet these 3 documents were not recognized, so the solution is not as functional as expected (I tried the two responses linked above)
How to resolve to detect mime-type?
For now there’s no way, at least I have not found any solution that uses for example a copy of the file MAGIC
(https://linux.die.net/man/5/magic), then for now the nearest solution would be perhaps to check the ContenType
(even if it is something that can be manipulated) and appears application/octet-stream
then use a fallback to check the extension, something like this:
using System;
using System.IO;
using System.Linq;
...
string ContentType = UP_Dados.PostedFile.ContentType;
string FileName = UP_Dados.PostedFile.FileName;
bool validate = false;
string[] AllowedTypes = {
"application/excel",
"application/x-excel",
"application/ms-excel",
"application/x-msexcel",
"application/vnd.ms-excel",
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
};
//Para o fallback, acaso o navegador enviar a extensão octet-stream ou zip
string[] FallckExtensions = { ".xls", ".xlsx" };
string[] FallbackMimes = {
"application/zip",
"application/octet-stream",
"application/x-zip-compressed"
};
//Se ContentType for um dos FallbackMimes, então checa a extensão
if (FallbackMimes.Contains(ContentType)) {
string extension = Path.GetExtension(FileName).ToLower();
validate = FallckExtensions.Contains(extension);
} else {
//Se o ContentType enviado pelo navegador não for octet-stream ou zip testa o AllowedTypes
validate = AllowedTypes.Contains(ContentType);
}
Example in ideone
If not working with XLSX then remove from the script:
".xlsx"
of AllowedExtensions
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
of AllowedTypes
"application/zip"
and "application/x-zip-compressed"
of FallbackMimes
Note: If I find any better solution I will review the answer
What is the value that variable
Type
taking?– Bruno Costa