處理從oss下載文件偶發性文件內容爲空的問題

背景:
  使用url通過httpClient的get方法,從oss下載pdf文件,被下載的文件通過瀏覽器能正常查看和下載

問題:
  偶爾會出現一個下載文件爲0KB的情況

代碼:

GetMethod httpGet = new GetMethod(strUrlPath);
InputStream in = null;
FileOutputStream out = null;
try {
    HttpClient httpClient = new HttpClient();
    httpClient.executeMethod(httpGet);
    in = httpGet.getResponseBodyAsStream();
    out = new FileOutputStream(new File(strLocalPath));
    byte[] b = new byte[1024];
    int len = 0;
    while ((len = in.read(b)) != -1) {
        out.write(b, 0, len);
    }
    in.close();
    out.close();
} catch (Exception e) {
    log.error("httpClient下載文件失敗", e);
} finally {
    httpGet.releaseConnection();
    try {
        if (in != null) {
            in.close();
        }
        if (out != null) {
            out.close();
        }
    } catch (Exception e1) {
        log.error("文件流信息關閉失敗", e1);
    }
}

分析過程:

  1.  因爲 FileOutputStream 沒有調用flush方法,認爲是數據未從緩存區刷入到系統,就關閉了輸出流,導致文件爲0KB。結果發現分析錯誤,通過查看源碼發現 flush 方法是 OutputStream 的方法,是個空實現。FileOutputStream 繼承了 OutputStream 並未重寫其 flush 方法,所以 FileOutputStream 是直接寫入系統緩存。
  2.  通過查看資料,瞭解到輸出流持久化文件是一個異步的過程。首先輸出流將字節寫入系統緩存,系統緩存會直接返回寫入結果。然後系統緩存會排隊將內容持久化。那我們可以將該過程變爲一個同步過程麼?答案是可以的。通過調用輸出流的 FileOutputStream.getFD().sync() 方法,同步等待文件持久化之後返回結果。至此問題解決。

 
    注意:使用 FileOutputStream.getFD().sync() 同步方法,對文件寫入的性能影響較大,是否需要使用還需要根據具體業務進行權衡。

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