zoukankan      html  css  js  c++  java
  • 下载文件使用缓存(一次性读取到内存),优化性能(注意静态对象修改需要加锁)

    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. 请求下载地址http://localhost:8080/mytest/downloadClient/test.exe

    注意: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();

  • 相关阅读:
    android 保存图片,及将图片更新到图库
    android 点击数字跳转到电话界面
    使用Picasso将加载的图片变成圆形
    如何获取listview里面的edittext或者RadioGroup的值,涉及到引发的混乱现象
    返回页面,并将此页面数据刷新一遍
    DrawerLayout建立侧滑时,显示侧滑页面,底层页面仍可以有点击响应,解决办法。
    实现双击退出程序
    sql语句查找某一列的值得最大值。
    vue 实战笔记一项目准备
    node的基础知识
  • 原文地址:https://www.cnblogs.com/qqzy168/p/2671619.html
Copyright © 2011-2022 走看看