代码改变世界

Java从url链接下载文件

2022-08-23 19:54  young柠檬味  阅读(4674)  评论(0编辑  收藏  举报

最近需要测试部分下载接口,于是便写了一个这个代码,通过Java编码实现从URL下载文件

import org.apache.commons.lang.StringUtils;
import java.io.*;
import java.net.*;

public class DownloadsFile {

    /**
     * 从Url中下载文件
     *
     * @param urlStr url的路径
     * @throws IOException
     */
    public static void downloadByUrl(String urlStr, String savePath) {

        try {
            URL url = new URL(urlStr);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            //设置超时间为5秒
            conn.setConnectTimeout(5 * 1000);
            //防止屏蔽程序抓取而返回403错误
            conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
            //设置部分请求头信息,根据自己的实际需要来书写,不需要的也可以删掉
            conn.setRequestProperty("api_token","Bearer_");
            conn.setRequestProperty("Cookie","XXL_JOB_LOGIN_IDENTITY=");
            //得到输入流
            InputStream inputStream = conn.getInputStream();
            //获取自己数组
            byte[] getData = readInputStream(inputStream);
            //文件保存位置
            File saveDir = new File(savePath);
            if (!saveDir.exists()) { // 没有就创建该文件
                saveDir.mkdir();
            }
            //获取文件名及后缀
            String headerField = conn.getHeaderField("Content-Disposition");
            String[] split = headerField.split("\"");
            String fileName = URLDecoder.decode(split[1], "utf-8");
						//开始写入
            File file = new File(saveDir + File.separator + fileName);
            FileOutputStream fos = new FileOutputStream(file);
            fos.write(getData);
            fos.close();
            inputStream.close();
            System.out.println("the file: " + url + " download success");
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    /**
     * 从输入流中获取字节数组
     *
     * @param inputStream
     * @return
     * @throws IOException
     */
    private static byte[] readInputStream(InputStream inputStream) throws IOException {
        byte[] buffer = new byte[4 * 1024];
        int len = 0;
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        while ((len = inputStream.read(buffer)) != -1) {
            bos.write(buffer, 0, len);
        }
        bos.close();
        return bos.toByteArray();
    }

    /**
     * 若URL为https://www.w3school.com.cn/example/xmle/note.xml这种
     * 则可以使用如下的方法,从下载路径中分割出文件的名字及后缀
     * 若为另一种http://10.10.101.101:8080/open/download/45
     * 需要从响应头中获取,具体看代码
     * @param url
     * @return
     */
    private static String getFileName(String url) {
        return StringUtils.substringAfterLast(url, "/");

    }

    public static void main(String[] args) {
        try {
            String filePath = "https://docs.spring.io/spring-framework/docs/4.2.0.RC1/spring-framework-reference/pdf//spring-framework-reference.pdf";
            filePath = "https://www.w3school.com.cn/example/xmle/note.xml";
            filePath="http://10.10.101.101:8080/open/download/45";
            downloadByUrl(filePath, "Documents");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

注:正常直接利用conn.getHeaderField("Content-Disposition")获取到的响应头信息格式是

Content-Disposition: attachment; filename="%A7%84%E8%8C%83-20220715.docx"

但是只需要filename部分,且filename编码乱码,因此首先使用字符串的分割方法将filename分割出来:

String.split("\"")

分割之后的数据又因为上传时起编码的问题,会是乱码,使用:

URLDecoder.decode()

将编码后的中文再解码,便可以得到原始的文件格式。