java下载远程url文件保存到本地 使用URL下载远程文件保存到本地

Java远程文件下载

      java下载远程url文件保存到本地 使用URL下载远程文件保存到本地

 

一、需求说明

1、项目中使用到一个第三方插件,因插件经常更新,人工一次次的替换,很麻烦。于是乎有了需求,使用代码实现后台自动下载更新。

2、因是java的服务端项目,这里使用JDK提供的 java.net.* 包的,URLHttpURLConnection 实现文件下载。

 

二、代码如下

1、使用url 下载远程文件

/**
	 * description: 使用url 下载远程文件
	 * @param urlPath  --- url资源
	 * @param targetDirectory --- 目标文件夹
	 * @throws Exception
	 * @return void
	 * @version v1.0
	 * @author w
	 * @date 2019年9月3日 下午8:29:01
	 */
	public static void download(String urlPath , String targetDirectory) throws Exception {
		// 解决url中可能有中文情况
		System.out.println("url:"+ urlPath);
		URL url = new URL(urlPath);
		HttpURLConnection http = (HttpURLConnection)url.openConnection();
		http.setConnectTimeout(3000);		
		// 设置 User-Agent 避免被拦截 
		http.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)");
		String contentType = http.getContentType();
		System.out.println("contentType: "+ contentType);
		// 获取文件大小 
		long length = http.getContentLengthLong();
		System.out.println("文件大小:"+(length / 1024)+"KB");
		// 获取文件名
		String fileName = getFileName(http , urlPath);
		InputStream inputStream = http.getInputStream();
		byte[] buff = new byte[1024*10];
		OutputStream out = new FileOutputStream(new File(targetDirectory,fileName));
		int len ;
		int count = 0; // 计数
		while((len = inputStream.read(buff)) != -1) {
			out.write(buff, 0, len);
			out.flush();
			++count ;
		}
		System.out.println("count:"+ count);
		// 关闭资源
		out.close();
		inputStream.close();
		http.disconnect();
	}

 

2、获取文件名

/**
	 * description: 获取文件名 
	 * @param http
	 * @param urlPath
	 * @throws UnsupportedEncodingException
	 * @return String
	 * @version v1.0
	 * @author w
	 * @date 2019年9月3日 下午8:25:55
	 */
	private static String getFileName(HttpURLConnection http , String urlPath) throws UnsupportedEncodingException {
		String headerField = http.getHeaderField("Content-Disposition");
		String fileName = null ;
		if(null != headerField) {
			String decode = URLDecoder.decode(headerField, "UTF-8");
			fileName = decode.split(";")[1].split("=")[1].replaceAll("\"", "");
			System.out.println("文件名是: "+ fileName);
		}
		if(null == fileName) {
			// 尝试从url中获取文件名
			String[] arr  = urlPath.split("/");
			fileName = arr[arr.length - 1];
			System.out.println("url中获取文件名:"+ fileName);
		}
		return fileName;
	}

3、测试

public static void main(String[] args) {
	Map<String,String> map = new HashMap<>();
	map.put("下载图片", "http://i1.zhiaigou.com/uploads/tu/201908/9999/152a0cd3b5.jpg");
	map.put("下载中文图片", "http://47.93.217.218/chapter/downloadServlet?fileName=%E4%B8%AD%E6%96%87%E5%9B%BE%E7%89%87.jpg");
	map.put("下载QQ软件", "https://qd.myapp.com/myapp/qqteam/pcqq/PCQQ2019.exe");
	map.put("下载带中文文件", "http://32204.xc.mieseng.com/xiaz/%E8%BF%85%E9%9B%B7%E5%A4%8D%E6%B4%BB%E7%89%88@68_416334.exe");
map.put("该资源无法下载", "https://www.csc108.com/announcementNotice/showFile.json?id=685");
	try {
		for(String urlStr : map.values()) {
			download(urlStr, "E:/");
		}
	} catch (Exception e) {
		e.printStackTrace();
	}
		
	System.out.println("process over ...");
}

4、效果如下:

 

三、总结

1、这里只是用简单的使用 HttpURLConnection 实现从远程服务端获取文件下载,若有更高级需求,比如 爬虫,可以考虑使用 jsoup 来实现。

2、【二-2】中获取文件名,静态资源直接从url中获取,动态返回的文件流资源,需要从header中获取。 比如参考:https://blog.youkuaiyun.com/HaHa_Sir/article/details/79258556

3、若服务端设置了禁用java等方式访问,该代码可能无效,回抛出异常: Server returned HTTP response code: 521 for URL: xxx . 该示例代码中没有解决这个问题!

 

 

Java 后端从远程 URL 下载文件保存本地服务器,然后通过 Vue 前端触发下载的流程可以分为以下几个部分: ### 后端(Java + Spring Boot) 1. **下载远程文件** 使用 `HttpURLConnection` 或 `HttpClient` 从远程 URL 下载文件内容,将其保存到服务器本地文件系统中。以下是使用 `HttpURLConnection` 的示例代码: ```java import java.io.*; import java.net.HttpURLConnection; import java.net.URL; public void downloadFileFromURL(String fileURL, String savePath) throws IOException { URL url = new URL(fileURL); HttpURLConnection httpConn = (HttpURLConnection) url.openConnection(); httpConn.setRequestMethod("GET"); int responseCode = httpConn.getResponseCode(); if (responseCode == HttpURLConnection.HTTP_OK) { try (InputStream inputStream = httpConn.getInputStream(); FileOutputStream outputStream = new FileOutputStream(savePath)) { byte[] buffer = new byte[4096]; int bytesRead; while ((bytesRead = inputStream.read(buffer)) != -1) { outputStream.write(buffer, 0, bytesRead); } } } else { throw new IOException("No file to download. Server replied HTTP code: " + responseCode); } httpConn.disconnect(); } ``` 2. **提供文件下载接口** 创建一个 Spring Boot 控制器,用于提供文件下载服务。该接口将读取本地存储的文件将其作为响应返回给前端。 ```java import org.springframework.core.io.InputStreamResource; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; @RestController public class FileDownloadController { private static final String FILE_PATH = "/path/to/saved/file.txt"; // 本地文件路径 @GetMapping("/download") public ResponseEntity<InputStreamResource> downloadFile() throws FileNotFoundException { File file = new File(FILE_PATH); FileInputStream fileInputStream = new FileInputStream(file); InputStreamResource resource = new InputStreamResource(fileInputStream); return ResponseEntity.ok() .header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + file.getName()) .contentType(MediaType.APPLICATION_OCTET_STREAM) .contentLength(file.length()) .body(resource); } } ``` ### 前端(Vue.js) 在 Vue 前端中,可以使用 `axios` 或直接通过 `window.location` 触发后端提供的下载接口。 1. **使用 `axios` 下载文件** 通过 `axios` 请求文件使用 `Blob` 对象处理二进制流,实现文件下载: ```javascript import axios from 'axios'; async function downloadFile() { try { const response = await axios.get('http://your-api-url/download', { responseType: 'blob', // 必须设置为 blob 以处理二进制流 }); const url = window.URL.createObjectURL(new Blob([response.data])); const link = document.createElement('a'); link.href = url; link.setAttribute('download', 'file.txt'); // 设置下载文件名 document.body.appendChild(link); link.click(); link.remove(); } catch (error) { console.error('文件下载失败:', error); } } ``` 2. **直接使用 `window.location`** 如果不需要处理错误或进度,可以直接通过浏览器跳转触发下载: ```javascript window.location.href = 'http://your-api-url/download'; ``` ### 安全性与优化建议 - **文件路径管理**:确保文件存储路径安全,避免暴露服务器敏感目录。 - **文件名处理**:建议在后端动态生成文件名或从原始 URL 中提取文件名,避免硬编码。 - **发控制**:多个用户同时下载文件时,需考虑线程安全和资源释放。 - **缓存机制**:可引入缓存策略,避免重复下载相同远程文件[^2]。
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值