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