当我们谈下载时,要注意什么
写在前面
当我们谈下载时,要注意什么?IO?API?SDK?
一、基本知识
下载的过程就是 复制的过程,三个基本名词 Source File,Target File,传输工具
二、Source File
源文件,Java中常见3种源文件,
- 资源路径-Classpath
- 文件系统 - File System
- 磁盘目录
2.1、资源路径
常见场景很多,包括各种模板、手册(Word,Excel,PDF…),相关静态文件…
这里一般通过两个对象即可操作资源文件,可参考这里,
获取 输出、输入流,即可完成下载
2.2、文件系统
这里的场景是基于一个文件服务,目前很多的文件服务的选择
fastDfs、HDFS、GlusterFS、各种云盘、各种云的OSS对象存储、甚至某个超链接…等等都可定义为文件系统的存储方式
文件系统的文件操作方法是基于 API,或者 超链接方式,即可
这里有可用的 SDK 或者 相关工具类封装…完成下载
类似如下,apache common
public static void downloadWithApacheCommons(String url, String localFilename) {
int CONNECT_TIMEOUT = 10000;
int READ_TIMEOUT = 10000;
try {
FileUtils.copyURLToFile(new URL(url), new File(localFilename), CONNECT_TIMEOUT, READ_TIMEOUT);
} catch (IOException e) {
e.printStackTrace();
}
}
2.3、磁盘目录
这里需要注意,开发环境,测试环境。以及生产环境因系统不同,文件分割符会有所不同
is = new FileInputStream(filePath + "\\" + path.getFileName()); // windows
is = new FileInputStream(filePath + "/" + path.getFileName()); // linux 目录分隔符
JDK 中 File.separator 可自动识别系统分隔符,因此上述可替换为
is = new FileInputStream(filePath + File.separator + path.getFileName());
还要注意 ,Java 项目 和 Springboot 项目测试中的差别,即springboot 项目中的 所获取Path路径是相对路径,会把磁盘某文件真实路径,映射 当前项目下,导致无法获取真实文件路径,获取输入流失败,可参考上述,拼接文件的完整路径,获取输入流
三、Target File
这里是指期望下载文件到某位置,一般通过浏览器方式下载(通过输出流写到浏览器默认下载目录)
四、传输工具
这里是指 IO 流的 读写方式,包括 字符流、字节流
示例(指向磁盘目录下载)
这里完成了 指向目标目录,过滤文件,下载
// 接口定义
@GetMapping("/manual")
public void manualDownload(HttpServletResponse response) {
InputStream is = null;
ServletOutputStream os = null;
String filePath = configService.findDefaultFilePath();
if (filePath == null) {
throw new CustomeException("文件地址为空");
}
List<Path> results = new LinkedList<Path>();
try {
Files.walkFileTree(Paths.get(filePath), new FindJavaVisitor(results));
if (results.size() != 1) {
throw new CustomeException("文件异常" + results.size());
}
Path path = results.get(0);
is = new FileInputStream(filePath + File.separator + path.getFileName());
response.addHeader("charset", "utf-8");
String encodeName = URLEncoder.encode(path.getFileName().toString(), StandardCharsets.UTF_8.toString());
response.setHeader("Content-Disposition", "attachment; filename=\"" + encodeName + "\"; filename*=utf-8''" + encodeName);
// copy (输入流,输出流)
os = response.getOutputStream();
IOUtils.copy(is, os);
response.flushBuffer();
} catch (Exception e) {
throw new CustomeException("文件异常");
} finally {
try {
if (os != null) {
os.close();
}
if (is != null) {
is.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
// 文件过滤
private static class FindJavaVisitor extends SimpleFileVisitor<Path> {
private List<Path> result;
public FindJavaVisitor(List<Path> result) {
this.result = result;
}
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
if (file.toString().endsWith(".docx")) {
result.add(file.getFileName());
}
return FileVisitResult.CONTINUE;
}
}