Java从重定向的'友好'URL获取下载文件名

时间:2012-11-02 10:38:48

标签: java redirect download url-routing nio

我正在尝试从给定的网址下载文件,该文件可能是也可能不是该文件的直接链接。如果URL是间接链接(即http://www.example.com/download.php?getFile=1),是否有人知道如何检测要写入的文件名? 如果URL是从URL提取文件名并开始写入提取的文件名的直接链接没有问题,但是使用重定向链接我到目前为止找到的唯一方法是写入任意文件名 - foo.txt - 然后尝试使用它。问题是我真的需要文件名(和扩展名)是正确的。 我正在使用的代码示例是:('else'子句中的部分既没有完成也没有工作):

public static boolean dlFile(String URL, String dest){
    try{
        URL grab = new URL(URL);
        ReadableByteChannel rbc = Channels.newChannel(grab.openStream());
        String fnRE = ".*/([a-zA-Z0-9\\-\\._]+)$";
            Pattern pattern = Pattern.compile(fnRE);
        Matcher matcher = pattern.matcher(URL);
        String fName = "";
        if(matcher.find()) fName = matcher.group(1);
        else { //filename cannot be extracted - do something here - below doesn't work raises MalformedURLExcpetion
            URL foo = new URL(URL);
            HttpURLConnection fooConnection = (HttpURLConnection) foo.openConnection();
            URL secondFoo = new URL(fooConnection.getHeaderField("Location"));
            System.out.println("Redirect URL: "+secondFoo);
            fooConnection.setInstanceFollowRedirects(false);
            URLConnection fooURL = secondFoo.openConnection();
        }
        System.out.println("Connection to "+URL+" established!");
        if(dest.endsWith("/")){}
        else dest+="/";
        System.out.println("Writing "+fName+" to "+dest);
        FileOutputStream fos = new FileOutputStream(dest+fName);
        fos.getChannel().transferFrom(rbc, 0, 1 << 24);

我确信必须有一个简单的方法从标题或类似的东西中获取文件名,但我无法弄清楚如何获取它。提前谢谢,

3 个答案:

答案 0 :(得分:2)

假设响应有一个&#34;位置&#34;标题字段,我能够获得直接链接到包含多个重定向的网址,如下所示:

String location = "http://www.example.com/download.php?getFile=1";
HttpURLConnection connection = null;
for (;;) {
    URL url = new URL(location);
    connection = (HttpURLConnection) url.openConnection();
    connection.setInstanceFollowRedirects(false);
    String redirectLocation = connection.getHeaderField("Location");
    if (redirectLocation == null) break;
    location = redirectLocation;
}
//and finally:
String fileName = location.substring(location.lastIndexOf('/') + 1, location.length());

答案 1 :(得分:0)

不,一般没办法。响应通常不包含该信息,因为您没有向数据流添加任何自己的协议信息(如果您可以控制服务器)。

无论如何,你要求文件扩展名。也许正确的content-type已经完成了。

答案 2 :(得分:0)

我认为最好使用Java Jsoup库,然后使用以下方法:

public static void downloadFileJsoup(String URL, String PATH) throws IOException {
    Response res = Jsoup.connect(URL)
            .userAgent("Mozilla")
            .timeout(30000)
            .followRedirects(true)
            .ignoreContentType(true)
            .maxBodySize(20000000)//Increase value if download is more than 20MB
            .execute(); 
    String remoteFilename=res.header("Content-Disposition").replaceFirst("(?i)^.*filename=\"?([^\"]+)\"?.*$", "$1");
    String filename = PATH + remoteFilename;
    FileOutputStream out = (new FileOutputStream(new java.io.File(filename)));
    out.write( res.bodyAsBytes());
    out.close();
}