How can I get MIME type of an InputStream of a file that is being uploaded?

前端 未结 8 1378
离开以前
离开以前 2020-12-30 21:51

Simple question: how can I get MIME type (or content type) of an InputStream, without saving file, for a file that a user is uploading to my servlet?

8条回答
  •  慢半拍i
    慢半拍i (楼主)
    2020-12-30 22:20

    I'm a big proponent of "do it yourself first, then look for a library solution". Luckily, this case is just that.

    You have to know the file's "magic number", i.e. its signature. Let me give an example for detecting whether the InputStream represents PNG file.

    PNG signature is composed by appending together the following in HEX:

    1) error-checking byte

    2) string "PNG" as in ASCII:

         P - 0x50
         N - 0x4E
         G - 0x47
    

    3) CR (carriage return) - 0x0D

    4) LF (line feed) - 0xA

    5) SUB (substitute) - 0x1A

    6) LF (line feed) - 0xA

    So, the magic number is

    89   50 4E 47 0D 0A 1A 0A
    
    137  80 78 71 13 10 26 10 (decimal)
    -119 80 78 71 13 10 26 10 (in Java)
    

    Explanation of 137 -> -119 conversion

    N bit number can be used to represent 2^N different values. For a byte (8 bits) that is 2^8=256, or 0..255 range. Java considers byte primitives to be signed, so that range is -128..127. Thus, 137 is considered to be singed and represent -119 = 137 - 256.

    Example in Koltin

    private fun InputStream.isPng(): Boolean {
        val magicNumbers = intArrayOf(-119, 80, 78, 71, 13, 10, 26, 10)
        val signatureBytes = ByteArray(magicNumbers.size)
        read(signatureBytes, 0, signatureBytes.size)
        return signatureBytes.map { it.toInt() }.toIntArray().contentEquals(magicNumbers)
    }
    

    Of course, in order to support many MIME types, you have to scale this solution somehow, and if you are not happy with the result, consider some library.

提交回复
热议问题