下载文件使用缓存(一次性读取到内存),优化性能(注意静态对象修改需要加锁)
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); resp.setContentType("application/x-msdownload");
|