Java 如何在URL上检测文件的真实类型?

Java 如何在URL上检测文件的真实类型?,java,android,file,Java,Android,File,通常,扩展名为.jpg的URL可能是.gif或.mp4类型的文件,反之亦然。有没有一种方法可以在不下载整个文件的情况下准确地确定URL包含的文件类型 例如: 它有.jpg扩展名,但实际上是.gif。注意:我的解决方案需要: compile 'com.google.guava:guava:19.0' 因为它提供了ByteStreams.toByteArray函数来从输入流获取字节数组。当然,您可以使用其他方法来读取输入流 注意:StrictMode.ThreadPolicy是必需的,否则会出现异

通常,扩展名为.jpg的URL可能是.gif或.mp4类型的文件,反之亦然。有没有一种方法可以在不下载整个文件的情况下准确地确定URL包含的文件类型

例如:


它有.jpg扩展名,但实际上是.gif。

注意:我的解决方案需要:

compile 'com.google.guava:guava:19.0'
因为它提供了
ByteStreams.toByteArray
函数来从输入流获取字节数组。当然,您可以使用其他方法来读取输入流

注意:
StrictMode.ThreadPolicy
是必需的,否则会出现异常

基本上,我们创建一个HTTP连接,但只请求远程url文件的第一个单字节。所以我们不需要下载整个文件。 然后通过
bytestohex
函数传递字节数组,将其作为原始字节。最后,将第一个字节的签名与我从该url获得的您的要求进行比较:

有关其他文件类型和文件字节的签名,您可以参考:

代码:

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState); 
    StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
    StrictMode.setThreadPolicy(policy);
    try {
        detectTypeOfFile();
    } catch (IOException e) {
        System.out.println("URL: CRASH: " + e.getStackTrace());
        e.printStackTrace();
    }
}

final protected static char[] hexArray = "0123456789ABCDEF".toCharArray();
public static String bytesToHex(byte[] bytes) {
    //http://stackoverflow.com/questions/9655181/how-to-convert-a-byte-array-to-a-hex-string-in-java
    char[] hexChars = new char[bytes.length * 2];
    for ( int j = 0; j < bytes.length; j++ ) {
        int v = bytes[j] & 0xFF;
        hexChars[j * 2] = hexArray[v >>> 4];
        hexChars[j * 2 + 1] = hexArray[v & 0x0F];
    }
    return new String(hexChars);
}

public void detectTypeOfFile() throws IOException {

    String[] urls = {"http://i.imgur.com/9b4bIW9.jpg","http://i.imgur.com/f00y2uz.jpg","http://i.imgur.com/9b4bIW9.mp4","http://i.imgur.com/9b4bIW9.gif"};

    for (int i=0;i<urls.length;i++){
        URL url = new URL(urls[i]);
        HttpURLConnection connection = ((HttpURLConnection) url.openConnection());
        connection.setRequestProperty("Range", "bytes="+0+"-"+0);
        connection.connect();
        byte[] bytes = ByteStreams.toByteArray(connection.getInputStream());
        System.out.println("URL: " + url.toString() + "  is of type: " + bytesToHex(bytes));
        switch (bytesToHex(bytes)) {
            //http://www.garykessler.net/library/file_sigs.html
            case "00":
                System.out.println("URL: " + url.toString() + "  is of type: mp4");
                break;
            case "FF":
                System.out.println("URL: " + url.toString() + "  is of type: image/jpeg");
                break;
            case "89":
                System.out.println("URL: " + url.toString() + "  is of type: image/png");
                break;
            case "47":
                System.out.println("URL: " + url.toString() + "  is of type: image/gif");
                break;
            case "49":
            case "4D":
                System.out.println("URL: " + url.toString() + "  is of type: image/tiff");
                break;
        }
        connection.disconnect();
    }
}
06-05 01:51:47.022 12554-12554/? I/System.out: URL: http://i.imgur.com/9b4bIW9.jpg  has first byte: 47
06-05 01:51:47.022 12554-12554/? I/System.out: URL: http://i.imgur.com/9b4bIW9.jpg  is of type: image/gif
06-05 01:51:47.056 12554-12554/? I/System.out: URL: http://i.imgur.com/f00y2uz.jpg  has first byte: FF
06-05 01:51:47.056 12554-12554/? I/System.out: URL: http://i.imgur.com/f00y2uz.jpg  is of type: image/jpeg
06-05 01:51:47.091 12554-12554/? I/System.out: URL: http://i.imgur.com/9b4bIW9.mp4  has first byte: 00
06-05 01:51:47.091 12554-12554/? I/System.out: URL: http://i.imgur.com/9b4bIW9.mp4  is of type: mp4
06-05 01:51:47.124 12554-12554/? I/System.out: URL: http://i.imgur.com/9b4bIW9.gif  has first byte: 47
06-05 01:51:47.124 12554-12554/? I/System.out: URL: http://i.imgur.com/9b4bIW9.gif  is of type: image/gif

耶,一个2年前的问题和一个解决方案刚刚被标记为重复??有点晚了,伙计。