java - 如何检测 URL 中文件的真实类型?

标签 java android file

<分区>

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

示例:http://i.imgur.com/9b4bIW9.jpg

这具有 .jpg 扩展名,但实际上是一个 .gif。

最佳答案

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

compile 'com.google.guava:guava:19.0'

因为它提供了 ByteStreams.toByteArray 函数来从输入流中获取字节数组。当然你可以使用一些其他的方法来读取输入流。

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

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

其他文件类型和文件字节签名可以引用: http://www.garykessler.net/library/file_sigs.html

代码:

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

关于java - 如何检测 URL 中文件的真实类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37638892/

相关文章:

java - 添加 META-INF/services 目录时 jar 中没有 .class 文件

java - 使用 Simple 将 HashMap 序列化为根元素

java - 如何将视频流从java发送到flex netstream?

android - 如何在android中添加占位符图像

java - 如何为现有驱动程序对象设置 Firefox 配置文件

java - 由于意外元素 "pool",JBoss 7.1.1 未启动

android - WSO2 IOTS 不会注册新的 Android 设备

使用 open() 写入之前清除文件

javascript - 如何在一个字段中选择一张图像,同时也将其选择到另一个字段中?

c++ - 逐行读取文本文件并计算比较运算符