处理从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() 同步方法,对文件写入的性能影响较大,是否需要使用还需要根据具体业务进行权衡。

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