@Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 取得参数 String contentPath = request.getParameter("contentPath"); if (StringUtils.isBlank(contentPath)) { response.sendError(HttpServletResponse.SC_BAD_REQUEST, "contentPath parameter is required."); return; } // 获取请求内容的基本信息. ContentInfo contentInfo = getContentInfo(contentPath); // 根据Etag或ModifiedSince Header判断客户端的缓存文件是否有效, 如仍有效则设置返回码为304,直接返回. if (!Servlets.checkIfModifiedSince(request, response, contentInfo.lastModified) || !Servlets.checkIfNoneMatchEtag(request, response, contentInfo.etag)) { return; } // 设置Etag/过期时间 Servlets.setExpiresHeader(response, Servlets.ONE_YEAR_SECONDS); Servlets.setLastModifiedHeader(response, contentInfo.lastModified); Servlets.setEtag(response, contentInfo.etag); // 设置MIME类型 response.setContentType(contentInfo.mimeType); // 设置弹出下载文件请求窗口的Header if (request.getParameter("download") != null) { Servlets.setFileDownloadHeader(request, response, contentInfo.fileName); } // 构造OutputStream OutputStream output; if (checkAccetptGzip(request) && contentInfo.needGzip) { // 使用压缩传输的outputstream, 使用http1.1 trunked编码不设置content-length. output = buildGzipOutputStream(response); } else { // 使用普通outputstream, 设置content-length. response.setContentLength(contentInfo.length); output = response.getOutputStream(); } // 高效读取文件内容并输出,然后关闭input file FileUtils.copyFile(contentInfo.file, output); output.flush(); }