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();

  • 相关阅读:
    【数据结构】线性表&&顺序表详解和代码实例
    【智能算法】超详细的遗传算法(Genetic Algorithm)解析和TSP求解代码详解
    【智能算法】用模拟退火(SA, Simulated Annealing)算法解决旅行商问题 (TSP, Traveling Salesman Problem)
    【智能算法】迭代局部搜索(Iterated Local Search, ILS)详解
    10. js时间格式转换
    2. 解决svn working copy locked问题
    1. easyui tree 初始化的两种方式
    10. js截取最后一个斜杠后面的字符串
    2. apache整合tomcat部署集群
    1. apache如何启动
  • 原文地址:https://www.cnblogs.com/qqzy168/p/2671619.html
Copyright © 2011-2022 走看看