ContentType property always contains "application/octet-stream"

May 26, 2008 at 11:47 PM
Why does the HttpPostedFile.ContentType property always contain "application/octet-stream"? When I upload an image and expect it to contain "image/jpeg" etc.
Coordinator
May 28, 2008 at 10:51 PM
When you upload file this is an application/octet-stream content type. Once its uploaded and you access it from the browser it will be image/jpeg. Thus you can have two files in one request and they can be of different types.

Why are you concerned with that?
May 29, 2008 at 1:58 AM
Edited May 29, 2008 at 2:01 AM
I wrote my own adapter to insert the file into a database as a binary image. The uploaded file is never saved to the disk and goes directly into the database. I store the ContentType in a seperate column so that I can set the correct MIME type in the HTTP respone when retreiving it back again. With the standard Microsoft FileUpload control the ContentType property displays the correct value. As a workaround I am now using MimeDetector to generate the MIME type for me.

http://www.netomatix.com/Products/DocumentManagement/MimeDetector.aspx
Coordinator
May 29, 2008 at 6:07 AM
The difference is that in this component the file comes from the flash player. Here is another solution to get MIME type from the registry:

public static string GetMimeTypeByFileName(string filepath)
{

    var regPerm = new RegistryPermission(RegistryPermissionAccess.Read, "\\\\HKEY_CLASSES_ROOT");
    var classesRoot = Registry.ClassesRoot;
   
    var typeKey = classesRoot.OpenSubKey("MIME\\Database\\Content Type");
    if (typeKey != null)
    {
        foreach (var keyname in typeKey.GetSubKeyNames())
        {
            var curKey = classesRoot.OpenSubKey("MIME\\Database\\Content Type\\" + keyname);
            if (curKey != null && String.Compare(curKey.GetValue("Extension") + "", dotExt, true) == 0)
            {
                return keyname;
            }
        }
    }
    return "application/octet-stream";
}

Coordinator
May 29, 2008 at 6:09 AM
Edited Jun 3, 2008 at 5:24 AM

... or I got this list from my registry:

Dictionary<string, string> KnownMimeTypes = new Dictionary<string, string>(StringComparer.CurrentCultureIgnoreCase)
{
  {".rar","application/x-rar-compressed"},
  {".gg","app/gg"},
  {".fif","application/fractals"},
  {".spl","application/futuresplash"},
  {".hta","application/hta"},
  {".hqx","application/mac-binhex40"},
  {".mp4","application/mpeg4"},
  {".vsi","application/ms-vsi"},
  {".mdb","application/msaccess"},
  {".doc","application/msword"},
  {".pdf","application/pdf"},
  {".p10","application/pkcs10"},
  {".p7c","application/pkcs7-mime"},
  {".p7s","application/pkcs7-signature"},
  {".cer","application/pkix-cert"},
  {".crl","application/pkix-crl"},
  {".ps","application/postscript"},
  {".rss","application/rss+xml"},
  {".sdp","application/sdp"},
  {".smi","application/smil"},
  {".edn","application/vnd.adobe.edn"},
  {".pdx","application/vnd.adobe.pdx"},
  {".rmf","application/vnd.adobe.rmf"},
  {".xdp","application/vnd.adobe.xdp+xml"},
  {".xfd","application/vnd.adobe.xfd+xml"},
  {".xfdf","application/vnd.adobe.xfdf"},
  {".fdf","application/vnd.fdf"},
  {".kml","application/vnd.google-earth.kml"},
  {".kmz","application/vnd.google-earth.kmz"},
  {".xls","application/vnd.ms-excel"},
  {".sst","application/vnd.ms-pki.certstore"},
  {".pko","application/vnd.ms-pki.pko"},
  {".cat","application/vnd.ms-pki.seccat"},
  {".stl","application/vnd.ms-pki.stl"},
  {".ppt","application/vnd.ms-powerpoint"},
  {".wpl","application/vnd.ms-wpl"},
  {".xps","application/vnd.ms-xpsdocument"},
  {".rm","application/vnd.rn-realmedia"},
  {".rnx","application/vnd.rn-realplayer"},
  {".rsml","application/vnd.rn-rsml"},
  {".adobebridge","application/x-bridge-url"},
  {".z","application/x-compress"},
  {".tgz","application/x-compressed"},
  {".etd","application/x-ebx"},
  {".gz","application/x-gzip"},
  {".itms","application/x-itunes-itms"},
  {".itpc","application/x-itunes-itpc"},
  {".jnlp","application/x-java-jnlp-file"},
  {".jtx","application/x-jtx+xps"},
  {".latex","application/x-latex"},
  {".nix","application/x-mix-transfer"},
  {".mxp","application/x-mmxp"},
  {".amc","application/x-mpeg"},
  {".asx","application/x-mplayer2"},
  {".application","application/x-ms-application"},
  {".slupkg-ms","application/x-ms-license"},
  {".vsto","application/x-ms-vsto"},
  {".wmd","application/x-ms-wmd"},
  {".wmz","application/x-ms-wmz"},
  {".xbap","application/x-ms-xbap"},
  {".pinstall","application/x-picasa-detect"},
  {".p12","application/x-pkcs12"},
  {".p7b","application/x-pkcs7-certificates"},
  {".p7r","application/x-pkcs7-certreqresp"},
  {".pcast","application/x-podcast"},
  {".qtl","application/x-quicktimeplayer"},
  {".rtsp","application/x-rtsp"},
  {".swf","application/x-shockwave-flash"},
  {".xap","application/x-silverlight"},
  {".skype","application/x-skype"},
  {".sparc","application/x-sparc"},
  {".sit","application/x-stuffit"},
  {".tar","application/x-tar"},
  {".wtml","application/x-wtml"},
  {".wtt","application/x-wtt"},
  {".wwtfig","application/x-wwtfig"},
  {".zip","application/x-zip-compressed"},
  {".xaml","application/xaml+xml"},
  {".3gp","audio/3gpp"},
  {".3g2","audio/3gpp2"},
  {".AMR","audio/AMR"},
  {".au","audio/basic"},
  {".m4a","audio/m4a"},
  {".mp3","audio/mp3"},
  {".m3u","audio/mpegurl"},
  {".qcp","audio/vnd.qcelp"},
  {".wav","audio/wav"},
  {".aac","audio/x-aac"},
  {".ac3","audio/x-ac3"},
  {".aiff","audio/x-aiff"},
  {".caf","audio/x-caf"},
  {".gsm","audio/x-gsm"},
  {".wax","audio/x-ms-wax"},
  {".wma","audio/x-ms-wma"},
  {".ram","audio/x-pn-realaudio"},
  {".ra","audio/x-realaudio"},
  {".rms","audio/x-realaudio-secure"},
  {".divx","ICM.DIV4"},
  {".bmp","image/bmp"},
  {".gif","image/gif"},
  {".jp2","image/jp2"},
  {".jpg","image/jpeg"},
  {".jpeg","image/jpeg"},
  {".pict","image/pict"},
  {".png","image/png"},
  {".tiff","image/tiff"},
  {".rp","image/vnd.rn-realpix"},
  {".ico","image/x-icon"},
  {".pntg","image/x-macpaint"},
  {".qtif","image/x-quicktime"},
  {".sgi","image/x-sgi"},
  {".targa","image/x-targa"},
  {".mid","midi/mid"},
  {".dwfx","model/vnd.dwfx+xps"},
  {".p7m","pkcs7-mime"},
  {".css","text/css"},
  {".dlm","text/dlm"},
  {".htm","text/html"},
  {".txt","text/plain"},
  {".wsc","text/scriptlet"},
  {".rt","text/vnd.rn-realtext"},
  {".htc","text/x-component"},
  {".contact","text/x-ms-contact"},
  {".odc","text/x-ms-odc"},
  {".vcf","text/x-vcard"},
  {".xml","text/xml"},
  {".avi","video/avi"},
  {".flc","video/flc"},
  {".mpg","video/mpeg"},
  {".mov","video/quicktime"},
  {".sdv","video/sd-video"},
  {".rv","video/vnd.rn-realvideo"},
  {".m4v","video/x-m4v"},
  {".mps","video/x-mpeg"},
  {".mpeg","video/x-mpeg2a"},
  {".mpa","video/x-mpg"},
  {".wm","video/x-ms-wm"},
  {".wmv","video/x-ms-wmv"},
  {".wmx","video/x-ms-wmx"},
  {".wvx","video/x-ms-wvx"}
};
Then check it as 
public static string GetMimeTypeByFileName(string filepath)
{
    var dotExt = Path.GetExtension(filepath);
    string type;
    if(KnownMimeTypes.TryGetValue(dotExt, out type))
    {
        return type;
    }
    return "application/octet-stream";
}

May 29, 2008 at 10:08 AM
Yes it's easy to use the file extension (if you trust it) to look up the MIME type. For security reasons the MimeDetector API scans the file contents. I have tested renaming a .jpeg file to .txt and it still detected it as image/jpeg.
Coordinator
May 29, 2008 at 6:41 PM
I understand but the flash sends the files as a stream, there is property type in the flash FileReference but it is only the file extension.
May 29, 2008 at 11:27 PM
This is the code I am using to obtain the true MIME type.

            MimeTypes mimeTypes = new MimeTypes( "mime-types.xml" );
           
            byte[] fileBytes = new byte[ file.ContentLength ];
            file.InputStream.Read( fileBytes, 0, file.ContentLength );
           
            sbyte[] fileData = Winista.Mime.SupportUtil.ToSByteArray( fileBytes );
            MimeType mimeType = mimeTypes.GetMimeType( fileData ); 

I think you could easily do something similar to set your ContentType property before invoking the adapter. You can also download the MimeDetector source code and re-use it ata more detailed level if you prefer.

 

Coordinator
May 30, 2008 at 12:22 AM
First the ContentType property of HttpPostedFile is read only and second you may be wouldn't mind dependancy on third party assembly Winista.Mime but may be others would.

But thanks for the tip it would be useful for other people I am sure.
May 30, 2008 at 11:30 PM
Ah, yes I had overlooked the fact that HttpPostedFile is a Microsoft sealed class. Not quite sure what Flash does with it or how it ends up containing application/octet-stream.

Those people that don't want dependency on assembly Winista.Mime could always download the source code and extract what they need.
Coordinator
May 31, 2008 at 5:02 PM

I understand that you want your problem solved mahbouni, but with this tool we want to provide a working core functionality of a file upload without full trust requirement or any dependencies other than the dependency on flash 8.

But in order to satisfy the wide variety of needs that people may have around this component we designed it in this highly extendable way.

And you see the tool is free, open source with no ads and so on. Your idea is a great, so why don’t you create an adapter, something like FileUploaderWithContentType? You can create a project here in codeplex and link it to the FlajaxianFileUploader. How does it sound?

 

Jun 2, 2008 at 11:39 PM
It sounds like a good idea but I'm not 100% clear on what the adapter needs to do. I'm guessing you mean a FileSaverAdapter that checks the content type and saves it with the correct file extension. Possibly it could reject the file if the extension does not match the content type. How could a rejection be reported to the client code?
Coordinator
Jun 3, 2008 at 4:23 AM
You could throw an exception.

This could be your code:

namespace Abc{

  public class ContentTypeDetectorAdapter : FileUploaderAdapter
  {
      public override void ProcessFile(HttpPostedFile file, Hashtable state)
      {
          state["ContentType"] = GetContentTypeByStream(file.InputStream);
      }

      private string GetContentTypeByStream(Stream stream)
      {
          // here you get the right content type
            return ...
      }
  }

  public class FileSaverCustomAdapter : FileUploaderAdapter
  {
      public override void ProcessFile(HttpPostedFile file, Hashtable state)
      {
          // save file using content type -> state["ContentType"]
      }
  }
}

<%@ Register TagPrefix="abc" Namespace="Abc" Assembly="yourAssembly" %>

<fjx:FileUploader ID="FileUploader1" runat="server" >
    <Adapters>
        <abc:ContentTypeDetectorAdapter Runat="server" FolderName="UploadFolder" />
        <abc:FileSaverCustomAdapter Runat="server" FolderName="UploadFolder" />
    </Adapters>
</fjx:FileUploader>