作为服务端
作为客户端
下载url需要取请求服务端
如果是浏览器访问的话,相当于浏览器帮你做了url的encode是可以下载的
如果用代码的话,一般如下:
public static String downLoadFromUrl(String urlStr, String fileName, String savePath) {
try {
URL url = new URL(urlStr);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
// 设置超时间为30秒
conn.setConnectTimeout(60 * 1000);
// 防止屏蔽程序抓取而返回403错误
conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
// 得到输入流
InputStream inputStream = conn.getInputStream();
// 获取自己数组
byte[] getData = readInputStream(inputStream);
// 文件保存位置
File saveDir = new File(savePath);
if (!saveDir.exists()) {
saveDir.mkdir();
}
File file = new File(saveDir + File.separator + fileName);
FileOutputStream fos = new FileOutputStream(file);
fos.write(getData);
if (fos != null) {
fos.close();
}
if (inputStream != null) {
inputStream.close();
}
return saveDir + File.separator + fileName;
} catch (Exception e) {
e.printStackTrace();
}
return "";
}
第十行会报错FileNotFound.类似这样
java.io.FileNotFoundException: http://www.zzgcjyzx.com:8087/Front/AttachStorage/202101/J070/ff6ee790-137a-4807-bab0-6622339e0321/[E3506010601800136042001]国泰新点测试项目20210118新接口测试项目-1.ZZZF
at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1896)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1498)
at com.dfit.api.junziqian.service.SignFileUtils.downLoadFromUrl(SignFileUtils.java:29)
at com.dfit.api.basic.controller.ProcessControllerTest.t2(ProcessControllerTest.java:55)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:230)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:58)
解决办法
方法1:url特殊部分进行encode
@Test
public void t3() throws Exception {
String a = "http://www.zzgcjyzx.com:8087/Front/AttachStorage/202101/J070/ff6ee790-137a-4807-bab0-6622339e0321/";
String b = "[E3506010601800136042001]国泰新点测试项目20210118新接口测试项目-1.ZZZF";
String realUrl=a+URLEncoder.encode(b,"UTF-8");
System.out.println(realUrl);
String fileName = StringUtils.substringAfterLast(urls,"/");
SignFileUtils.downLoadFromUrl(realUrl, fileName, fileDir);
}
方法2:用http直接请求
hutool请求
String urls = "http://www.zzgcjyzx.com:8087/Front/AttachStorage/202101/J070/ff6ee790-137a-4807-bab0-6622339e0321/[E3506010601800136042001]国泰新点测试项目20210118新接口测试项目-1.ZZZF";
String fileDir = "d:/filestore/";
@Test
public void t1() throws Exception {
String fileName = StringUtils.substringAfterLast(urls,"/");
HttpUtil.downloadFile(urls, fileDir+fileName);
}
总结
两种思路都有一定局限性
方法1好像不知道特殊的符号在哪里
方法2暂时还不知道有啥问题
方法1优化:
HuTool URLUtil的方法可以帮我们对url进行转义
public static String normalize(String url, boolean isEncodePath) {
if (StrUtil.isBlank(url)) {
return url;
}
final int sepIndex = url.indexOf("://");
String protocol;
String body;
if (sepIndex > 0) {
protocol = StrUtil.subPre(url, sepIndex + 3);
body = StrUtil.subSuf(url, sepIndex + 3);
} else {
protocol = "http://";
body = url;
}
final int paramsSepIndex = StrUtil.indexOf(body, '?');
String params = null;
if (paramsSepIndex > 0) {
params = StrUtil.subSuf(body, paramsSepIndex);
body = StrUtil.subPre(body, paramsSepIndex);
}
if (StrUtil.isNotEmpty(body)) {
// 去除开头的\或者/
//noinspection ConstantConditions
body = body.replaceAll("^[\\\\/]+", StrUtil.EMPTY);
// 替换多个\或/为单个/
body = body.replace("\\", "/").replaceAll("//+", "/");
}
final int pathSepIndex = StrUtil.indexOf(body, '/');
String domain = body;
String path = null;
if (pathSepIndex > 0) {
domain = StrUtil.subPre(body, pathSepIndex);
path = StrUtil.subSuf(body, pathSepIndex);
}
if (isEncodePath) {
path = encode(path);
}
return protocol + domain + StrUtil.nullToEmpty(path) + StrUtil.nullToEmpty(params);
}
在方法1放url的地方,对url部分进行转义即可,还是同事老哥厉害