博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
下载文件使用缓存(一次性读取到内存),优化性能(注意静态对象修改需要加锁)...
阅读量:7072 次
发布时间:2019-06-28

本文共 5196 字,大约阅读时间需要 17 分钟。

1.web.xml的servlet配置

<servlet>

  <servlet-name>downloadServlet</servlet-name>
  <servlet-class>
   com.huawei.download.DownloadServlet
  </servlet-class>
 </servlet>
 <servlet-mapping>
  <servlet-name>downloadServlet</servlet-name>
  <url-pattern>/downloadClient/*</url-pattern>
 </servlet-mapping>

2.DownloadServlet

 public class DownloadServlet extends HttpServlet

{

 @Override

 protected void doGet(HttpServletRequest req, HttpServletResponse resp)
   throws ServletException, IOException
 {
  doPost(req, resp);
 }

 @Override

 protected void doPost(HttpServletRequest req, HttpServletResponse resp)
   throws ServletException, IOException
 {

  String url = req.getRequestURI();

  String resFileName = url.substring(url.lastIndexOf("/") + 1, url
    .length());
  String realPath = req.getRealPath("/");
  String exeFile = realPath + "download/test.exe";
  String kipFile = realPath + "download/test";
  PrintWriter out = resp.getWriter();
  byte[] bytes = null;
  OutputStream opts=null;
  if (DownloadManager.checkFileExist(exeFile, kipFile))
  {
   try
   {

   // 如果缓存数组为空或源文件有改动,则重新读取并缓存(注意加锁)

    DownloadManager.cheackIsUpdate(exeFile, kipFile);    

    bytes = DownloadManager.getDownloadBytes();

    resp.reset();

    resp.setContentType("application/x-msdownload");
    resp.setHeader("Content-Disposition", "attachment;filename="
      + resFileName);
    opts = resp.getOutputStream();
    opts.write(bytes);
  
    System.out
      .println("*************************************************");
    System.out.println("*    This Is Local Download Server!");
    System.out.println("*    User   IP: " + req.getRemoteAddr());
    System.out.println("*    Download File Time: "
      + new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
        .format(new java.util.Date()));
    System.out
      .println("*************************************************");

   } catch (Exception e)

   {
    System.out.println("read downloadfile error:" + e);
   }
   finally
   {
    opts.close();
   }

  } else

  {
   out.println("<center>download file is not exsit!</center>");
  }
 }
}

3.DownloadManager

 public class DownloadManager

{
 private static byte[] downloadBytes = null;
 private static long exeFileLastModified = 0L;
 private static long kipFileLastModified = 0L;

 /**

  * 重新读取目标文件并缓存
  * 
    */
 public static void reReadDownloadBytes(String exeFile,
   String kipFile) throws Exception
 {

  File exe = new File(exeFile);

  File kip = new File(kipFile);
  setExeFileLastModified(exe.lastModified());
  setKipFileLastModified(kip.lastModified());
  BufferedInputStream buffer = null;
  ByteArrayOutputStream bos = null;
  try
  {
   buffer = new BufferedInputStream(new FileInputStream(exe));
   //目标文件exe文件大概300k,一次性读取
   int dataSize = 1024*300;
   byte[] bt = new byte[dataSize];
   int len = 0;
   bos = new ByteArrayOutputStream();
   while ((len = buffer.read(bt)) > 0)
   {
    bos.write(bt, 0, bt.length);
   }
  } catch (Exception e)
  {
   throw e;
  } finally
  {
   buffer.close();
   bos.close();
  }

  setDownloadBytes(bos.toByteArray());

  System.out.println("-------------reReading------------");
  System.out.println("-------------Time: "
    + new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
      .format(new java.util.Date()));
 }

 /**

  * 检测客户端目标文件是否存在
    */
 public static boolean checkFileExist(String exeFile, String kipFile)
 {
  File exe = new File(exeFile);
  File kip = new File(kipFile);

  if (kip.exists() && exe.exists())

  {
   return true;
  }
  return false;
 }

 /**

  * 检测检测目标文件否更新
  * 
    */
 public static boolean isFileModified(String exeFile, String kipFile)
 {
  File exe = new File(exeFile);
  File kip = new File(kipFile);

  long nowExeFileLastModified = exe.lastModified();

  long nowKipFileLastModified = kip.lastModified();

  if ((nowExeFileLastModified != getExeFileLastModified())

    || (nowKipFileLastModified != getKipFileLastModified()))
  {
   return true;
  }
  return false;
 }

 

/**

  * 判断是否需要重新读取文件(要加鎖)
  * 此方法虽然加锁,但是不耗时间
  * @throws Exception
  */
 public static synchronized void cheackIsUpdate(String exeFile, String kipFile) throws Exception
 {
  if (null == DownloadManager.getDownloadBytes()
    || DownloadManager.isFileModified(exeFile, kipFile))
  {
   DownloadManager.reReadDownloadBytes(exeFile,kipFile);
  }
 }

 

 public static byte[] getDownloadBytes()

 {
  return downloadBytes;
 }

 public static void setDownloadBytes(byte[] downloadBytes)

 {
  DownloadManager.downloadBytes = downloadBytes;
 }

 public static long getExeFileLastModified()

 {
  return exeFileLastModified;
 }

 public static long getKipFileLastModified()

 {
  return kipFileLastModified;
 }

 public static void setExeFileLastModified(long exeFileLastModified)

 {
  DownloadManager.exeFileLastModified = exeFileLastModified;
 }

 public static void setKipFileLastModified(long kipFileLastModified)

 {
  DownloadManager.kipFileLastModified = kipFileLastModified;
 }

}

4. 请求下载地址

 

注意:1.缓存下载文件,需要使用静态字节数组保存,样例中使用了两个输出的转换,很重要:

        2.注意静态对象修改需要加锁

File f = new File(exeFile);

    BufferedInputStream buffer = new BufferedInputStream(
      new FileInputStream(f));
    int dataSize = 1024*1024*10;
    byte[] bt = new byte[dataSize];
    int len = 0;
    resp.reset();

    resp.setContentType("application/x-msdownload");

    resp.setHeader("Content-Disposition", "attachment;filename="
      + resFileName);
    OutputStream out1 = resp.getOutputStream();
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    
    //判断
    
    while ((len = buffer.read(bt)) > 0)
    {
     bos.write(bt, 0, bt.length);
     //out1.write(bt, 0, len);
    }
    //bos.toByteArray()可以缓存
    out1.write(bos.toByteArray());
    
    
    buffer.close();
    out1.close();
    bos.close();

 

 

转载地址:http://btzml.baihongyu.com/

你可能感兴趣的文章
Android基础小技术点:Android ListView设置背景图片及分割线、周边距
查看>>
webpack配置(第四步:html篇(进阶篇))
查看>>
Spring Boot开启的2种方式
查看>>
阿里云服务提供商分享CDN访问异常该如何排查
查看>>
利用Sympy计算sin1°的最小多项式
查看>>
Vuejs响应式原理
查看>>
【Nebula系列】C++反射机制:可变参数模板实现C++反射
查看>>
tomcat报错
查看>>
MySQL之内联接、左联接、右联接、交叉联接
查看>>
使用 Buildah 创建小体积的容器
查看>>
Vue核心思想:数据驱动、组件化
查看>>
渗透测试流程
查看>>
第101天:CSS3中transform-style和perspective
查看>>
最完整的经纬度正则表达式
查看>>
Ubuntu MATE 推出树莓派版本
查看>>
数据智能创建能源领域“智能助手”
查看>>
深度学习将让图像处理变得简单通用
查看>>
奇异量子物理系统:它既在“绝对零度”之下,又在“绝对高温”之上
查看>>
Audacity 2.3.1 发布,恢复 Linux 支持
查看>>
干货云集 WOT2016峰会揭密大数据背后的技术难点
查看>>