Java从URL链接下载文件到本地

1,430 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第13天,点击查看活动详情

最近需要测试部分下载接口,于是便写了一个这个代码,通过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()

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