Java文件下載的幾點總結-當我們談下載時要注意什麼

寫在前面

當我們談下載時,要注意什麼?IO?API?SDK?

一、基本知識

下載的過程就是 複製的過程,三個基本名詞 Source File,Target File,傳輸工具

二、Source File

源文件,Java中常見3種源文件,

  • 資源路徑-Classpath
  • 文件系統 - File System
  • 磁盤目錄

2.1、資源路徑

常見場景很多,包括各種模板、手冊(Word,Excel,PDF…),相關靜態文件…

這裏一般通過兩個對象即可操作資源文件,可參考這裏,

springboot中,如何從資源文件加載文件

獲取 輸出、輸入流,即可完成下載

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;
        }
    }



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章