<分区>
扩展名为 .jpg 的 URL 通常会变成 .gif 或 .mp4 类型的文件,反之亦然。有没有一种方法可以在不下载整个文件的情况下准确找出 URL 包含的文件类型?
示例:http://i.imgur.com/9b4bIW9.jpg
这具有 .jpg 扩展名,但实际上是一个 .gif。
<分区>
扩展名为 .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/