2

我正在尝试从给定的 URL 下载文件,该 URL 可能是也可能不是文件的直接链接。如果 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);

我确信必须有一种简单的方法来从标题或类似的东西中获取文件名,但我不知道如何获取它。提前致谢,

4

3 回答 3

2

假设响应具有“位置”标头字段,我能够获得指向包含多个重定向的 url 的直接链接,如下所示:

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());
于 2016-03-02T09:54:27.190 回答
1

我认为最好使用 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();
}
于 2020-11-03T19:34:06.227 回答
0

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

无论如何,您要求提供文件扩展名。也许使用正确的内容类型就完成了。

于 2012-11-02T10:43:37.997 回答