8
\$\begingroup\$

I've written the following extension to determine the MIME type of a base64 string. It's worked in my local tests, but can anyone point out issues or alternate methods?

public static AttachmentType GetMimeType(this string value)
{
    if(String.IsNullOrEmpty(value))
        return new AttachmentType
                {
                    FriendlyName = "Unknown",
                    MimeType = "application/octet-stream",
                    Extension = ""
                };

    var data = value.Substring(0,5);

    switch (data.ToUpper())
    {
        case "IVBOR":
        case "/9J/4":
            return new AttachmentType
                {
                    FriendlyName = "Photo",
                    MimeType = "image/png",
                    Extension = ".png"
                };

        case "AAAAF":
            return new AttachmentType
                {
                    FriendlyName = "Video",
                    MimeType = "video/mp4",
                    Extension = ".mp4"
                };
        case "JVBER":
            return new AttachmentType
                {
                    FriendlyName = "Document",
                    MimeType = "application/pdf",
                    Extension = ".pdf"
                };

        default:
            return new AttachmentType
                {
                    FriendlyName = "Unknown",
                    MimeType = string.Empty,
                    Extension = ""
                };
    }
}

public class AttachmentType
{
    public string MimeType { get; set; }
    public string FriendlyName { get; set; }
    public string Extension { get; set; }
}
\$\endgroup\$
4
\$\begingroup\$

Your attachment types look like static data to me, so I'd personally make AttachmentType an immutable class and define your common bits as static members. I also like making things like this implement an interface for ease of mocking during unit testing. So I have this:

public interface IAttachmentType
{
    string MimeType
    {
        get;
    }

    string FriendlyName
    {
        get;
    }

    string Extension
    {
        get;
    }
}

public sealed class AttachmentType : IAttachmentType
{
    private static readonly IAttachmentType unknownMime =
        new AttachmentType("application/octet-stream", "Unknown", string.Empty);

    private static readonly IAttachmentType photo = new AttachmentType("image/png", "Photo", ".png");

    private static readonly IAttachmentType video = new AttachmentType("video/mp4", "Video", ".mp4");

    private static readonly IAttachmentType document = new AttachmentType("application/pdf", "Document", ".pdf");

    private static readonly IAttachmentType unknown = new AttachmentType(string.Empty, "Unknown", string.Empty);

    private readonly string mimeType;

    private readonly string friendlyName;

    private readonly string extension;

    // Possibly make this private if you only use the static predefined MIME types.
    public AttachmentType(string mimeType, string friendlyName, string extension)
    {
        this.mimeType = mimeType;
        this.friendlyName = friendlyName;
        this.extension = extension;
    }

    public static IAttachmentType UnknownMime
    {
        get
        {
            return unknownMime;
        }
    }

    public static IAttachmentType Photo
    {
        get
        {
            return photo;
        }
    }

    public static IAttachmentType Video
    {
        get
        {
            return video;
        }
    }

    public static IAttachmentType Document
    {
        get
        {
            return document;
        }
    }

    public static IAttachmentType Unknown
    {
        get
        {
            return unknown;
        }
    }

    public string MimeType
    {
        get
        {
            return this.mimeType;
        }
    }

    public string FriendlyName
    {
        get
        {
            return this.friendlyName;
        }
    }

    public string Extension
    {
        get
        {
            return this.extension;
        }
    }
}

Then, to avoid a big long switch, I put those into a Dictionary<T,U> as such (note the case-insensitive specification, which will remove the ToUpper() later). You can add MIME types with your detection string as needed:

    private static readonly IDictionary<string, IAttachmentType> mimeMap =
        new Dictionary<string, IAttachmentType>(StringComparer.OrdinalIgnoreCase)
        {
            { "IVBOR", AttachmentType.Photo },
            { "/9J/4", AttachmentType.Photo },
            { "AAAAF", AttachmentType.Video },
            { "JVBER", AttachmentType.Document }
        };

Your calling code then simplifies to:

    public static IAttachmentType GetMimeType(this string value)
    {
        IAttachmentType result;

        return string.IsNullOrEmpty(value)
            ? AttachmentType.UnknownMime
            : (mimeMap.TryGetValue(value.Substring(0, 5), out result) ? result : AttachmentType.Unknown);
    }
\$\endgroup\$
7
\$\begingroup\$

Your switch is wrong: "/9J/4" is for JPG images, not PNG (e.g. as shown in these examples).

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.