在spring boot中,可以通过url地址获取文件有多种方式。以下是几种常见的方法:
1. 使用 java 原生的 url 和 httpurlconnection
import java.io.*;
import java.net.httpurlconnection;
import java.net.url;
public class urlfiledownloader {
public static void downloadfile(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("http 请求失败,响应码: " + responsecode);
}
httpconn.disconnect();
}
}2. 使用 spring 的 resttemplate
import org.springframework.core.io.resource;
import org.springframework.http.responseentity;
import org.springframework.stereotype.service;
import org.springframework.web.client.resttemplate;
import org.springframework.core.io.filesystemresource;
import java.io.file;
import java.io.fileoutputstream;
import java.io.inputstream;
import java.nio.file.files;
import java.nio.file.path;
import java.nio.file.standardcopyoption;
@service
public class filedownloadservice {
private final resttemplate resttemplate;
public filedownloadservice(resttemplatebuilder resttemplatebuilder) {
this.resttemplate = resttemplatebuilder.build();
}
// 方法1:下载文件到本地
public file downloadfiletolocal(string fileurl, string localfilepath) throws ioexception {
responseentity<byte[]> response = resttemplate.getforentity(fileurl, byte[].class);
if (response.getstatuscode().is2xxsuccessful() && response.getbody() != null) {
file file = new file(localfilepath);
try (fileoutputstream fos = new fileoutputstream(file)) {
fos.write(response.getbody());
}
return file;
} else {
throw new ioexception("文件下载失败");
}
}
// 方法2:返回 resource
public resource downloadfileasresource(string fileurl, string localfilename) throws ioexception {
responseentity<byte[]> response = resttemplate.getforentity(fileurl, byte[].class);
if (response.getstatuscode().is2xxsuccessful() && response.getbody() != null) {
path tempfile = files.createtempfile(localfilename, ".tmp");
files.write(tempfile, response.getbody());
return new filesystemresource(tempfile.tofile());
}
throw new ioexception("文件下载失败");
}
// 方法3:流式下载大文件
public file downloadlargefile(string fileurl, string outputpath) throws ioexception {
return resttemplate.execute(fileurl, httpmethod.get, null, clienthttpresponse -> {
file file = new file(outputpath);
try (inputstream inputstream = clienthttpresponse.getbody();
fileoutputstream outputstream = new fileoutputstream(file)) {
byte[] buffer = new byte[8192];
int bytesread;
while ((bytesread = inputstream.read(buffer)) != -1) {
outputstream.write(buffer, 0, bytesread);
}
}
return file;
});
}
}3. 使用 resttemplate 配置类
import org.springframework.context.annotation.bean;
import org.springframework.context.annotation.configuration;
import org.springframework.web.client.resttemplate;
import org.springframework.http.client.simpleclienthttprequestfactory;
import org.springframework.boot.web.client.resttemplatebuilder;
import org.springframework.http.converter.bytearrayhttpmessageconverter;
import java.time.duration;
@configuration
public class resttemplateconfig {
@bean
public resttemplate resttemplate(resttemplatebuilder builder) {
return builder
.setconnecttimeout(duration.ofseconds(30))
.setreadtimeout(duration.ofseconds(60))
.additionalmessageconverters(new bytearrayhttpmessageconverter())
.build();
}
}4. 使用 webclient(响应式,spring 5+)
import org.springframework.core.io.resource;
import org.springframework.http.mediatype;
import org.springframework.stereotype.service;
import org.springframework.web.reactive.function.client.webclient;
import reactor.core.publisher.mono;
import java.nio.file.path;
import java.nio.file.paths;
@service
public class webclientfiledownloadservice {
private final webclient webclient;
public webclientfiledownloadservice(webclient.builder webclientbuilder) {
this.webclient = webclientbuilder.build();
}
public mono<resource> downloadfile(string fileurl) {
return webclient.get()
.uri(fileurl)
.accept(mediatype.application_octet_stream)
.retrieve()
.bodytomono(resource.class);
}
public mono<void> downloadtofile(string fileurl, string outputpath) {
return webclient.get()
.uri(fileurl)
.retrieve()
.bodytomono(byte[].class)
.flatmap(bytes -> {
try {
path path = paths.get(outputpath);
java.nio.file.files.write(path, bytes);
return mono.empty();
} catch (ioexception e) {
return mono.error(e);
}
});
}
}5. 完整的 controller 示例
import org.springframework.core.io.resource;
import org.springframework.core.io.bytearrayresource;
import org.springframework.http.httpheaders;
import org.springframework.http.mediatype;
import org.springframework.http.responseentity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.resttemplate;
import java.io.ioexception;
@restcontroller
@requestmapping("/api/files")
public class filedownloadcontroller {
private final resttemplate resttemplate;
private final filedownloadservice filedownloadservice;
public filedownloadcontroller(resttemplate resttemplate,
filedownloadservice filedownloadservice) {
this.resttemplate = resttemplate;
this.filedownloadservice = filedownloadservice;
}
// 直接返回文件流
@getmapping("/download")
public responseentity<resource> downloadfromurl(@requestparam string url)
throws ioexception {
responseentity<byte[]> response = resttemplate.getforentity(url, byte[].class);
if (response.getstatuscode().is2xxsuccessful() && response.getbody() != null) {
bytearrayresource resource = new bytearrayresource(response.getbody());
return responseentity.ok()
.contenttype(mediatype.application_octet_stream)
.header(httpheaders.content_disposition,
"attachment; filename=\"" + getfilenamefromurl(url) + "\"")
.body(resource);
}
return responseentity.notfound().build();
}
// 代理下载并保存到服务器
@postmapping("/proxy-download")
public responseentity<string> proxydownload(@requestparam string url,
@requestparam string savepath) {
try {
file file = filedownloadservice.downloadfiletolocal(url, savepath);
return responseentity.ok("文件已保存: " + file.getabsolutepath());
} catch (ioexception e) {
return responseentity.badrequest().body("下载失败: " + e.getmessage());
}
}
private string getfilenamefromurl(string url) {
string[] parts = url.split("/");
return parts[parts.length - 1];
}
}6. 添加依赖(maven)
<dependencies>
<!-- spring boot starter web -->
<dependency>
<groupid>org.springframework.boot</groupid>
<artifactid>spring-boot-starter-web</artifactid>
</dependency>
<!-- webclient 响应式支持 -->
<dependency>
<groupid>org.springframework.boot</groupid>
<artifactid>spring-boot-starter-webflux</artifactid>
</dependency>
</dependencies>7. 异常处理和优化建议
import org.springframework.web.client.restclientexception;
import org.springframework.web.client.httpclienterrorexception;
import org.springframework.web.client.httpservererrorexception;
@service
public class robustfiledownloadservice {
public void downloadwithretry(string fileurl, string outputpath, int maxretries) {
int retrycount = 0;
while (retrycount < maxretries) {
try {
// 下载逻辑
downloadfile(fileurl, outputpath);
return;
} catch (httpclienterrorexception e) {
// 客户端错误(4xx),通常不需要重试
throw e;
} catch (httpservererrorexception | restclientexception e) {
// 服务器错误(5xx)或网络错误,重试
retrycount++;
if (retrycount >= maxretries) {
throw e;
}
try {
thread.sleep(1000 * retrycount); // 指数退避
} catch (interruptedexception ie) {
thread.currentthread().interrupt();
}
}
}
}
// 设置超时和代理
public resttemplate resttemplatewithtimeout() {
simpleclienthttprequestfactory requestfactory = new simpleclienthttprequestfactory();
requestfactory.setconnecttimeout(5000);
requestfactory.setreadtimeout(30000);
// 设置代理(如果需要)
// proxy proxy = new proxy(proxy.type.http, new inetsocketaddress("proxy", 8080));
// requestfactory.setproxy(proxy);
return new resttemplate(requestfactory);
}
}使用示例
@springbootapplication
public class application implements commandlinerunner {
@autowired
private filedownloadservice filedownloadservice;
public static void main(string[] args) {
springapplication.run(application.class, args);
}
@override
public void run(string... args) throws exception {
// 下载文件示例
string fileurl = "https://example.com/path/to/file.pdf";
string savepath = "/tmp/downloaded-file.pdf";
file downloadedfile = filedownloadservice.downloadfiletolocal(fileurl, savepath);
system.out.println("文件已下载到: " + downloadedfile.getabsolutepath());
}
}注意事项
- 网络超时设置:合理设置连接和读取超时
- 异常处理:处理网络异常、文件不存在等情况
- 大文件处理:使用流式处理避免内存溢出
- 安全性:验证url,防止ssrf攻击
- 资源清理:确保流正确关闭
- 并发控制:大量下载时考虑使用连接池
- 文件类型验证:验证下载的文件类型是否符合预期
选择哪种方法取决于具体需求:
- 简单场景:使用
httpurlconnection - spring boot项目:使用
resttemplate - 响应式编程:使用
webclient - 大文件下载:使用流式处理
以上就是springboot通过url地址获取文件的多种方式的详细内容,更多关于springboot url地址获取文件的资料请关注代码网其它相关文章!
发表评论