java生成csv文件并通过浏览器下载

       最近在电信做业务的时候发现有一个导出csv文件的需求,一般导出使用POI直接导出excel即可,excel2007已经支持最多104.8万条记录,基本可以满足需求,为了尝试下导出csv文件,因此采用了导出csv文件的实现,csv即为逗号分隔值(Comma-Separated Values,CSV,有时也称为字符分隔值,因为分隔字符也可以不是逗号),可以使用excel直接打开预览。

       下面结合所使用的功能进行说明:

        首先创建一个CsvUtil.java类,包括删除已生成的csv文件、测试代码,代码如下:

public class CsvUtils {

 private static final org.apache.commons.logging.Log LOG = LogFactory
   .getLog(CsvUtils.class);

 /**
  * 生成为CVS文件
  *
  * @param exportData
  *            源数据List
  * @param map
  *            csv文件的列表头map
  * @param outPutPath
  *            文件路径
  * @param fileName
  *            文件名称
  * @return
  */
 @SuppressWarnings("rawtypes")
 public static File createCSVFile(List exportData, LinkedHashMap map,
   String outPutPath, String fileName) {
  File csvFile = null;
  BufferedWriter csvFileOutputStream = null;
  try {
   File file = new File(outPutPath);
   if (!file.exists()) {
    file.mkdir();
   }
   // 定义文件名格式并创建
   csvFile = File.createTempFile(fileName, ".csv",
     new File(outPutPath));
   LOG.debug("csvFile:" + csvFile);
   // UTF-8使正确读取分隔符","
   csvFileOutputStream = new BufferedWriter(new OutputStreamWriter(
     new FileOutputStream(csvFile), "GBK"), 1024);
   LOG.debug("csvFileOutputStream:" + csvFileOutputStream);
   // 写入文件头部
   for (Iterator propertyIterator = map.entrySet().iterator(); propertyIterator
     .hasNext();) {
    java.util.Map.Entry propertyEntry = (java.util.Map.Entry) propertyIterator
      .next();
    csvFileOutputStream
      .write("" + (String) propertyEntry.getValue() != null ? (String) propertyEntry
        .getValue() : "" + "");
    if (propertyIterator.hasNext()) {
     csvFileOutputStream.write(",");
    }
   }
   csvFileOutputStream.newLine();
   // 写入文件内容
   for (Iterator iterator = exportData.iterator(); iterator.hasNext();) {
    Object row = (Object) iterator.next();
    for (Iterator propertyIterator = map.entrySet().iterator(); propertyIterator
      .hasNext();) {
     java.util.Map.Entry propertyEntry = (java.util.Map.Entry) propertyIterator
       .next();
     csvFileOutputStream.write((String) BeanUtils.getProperty(
       row, (String) propertyEntry.getKey()));
     if (propertyIterator.hasNext()) {
      csvFileOutputStream.write(",");
     }
    }
    if (iterator.hasNext()) {
     csvFileOutputStream.newLine();
    }
   }
   csvFileOutputStream.flush();
  } catch (Exception e) {
   e.printStackTrace();
  } finally {
   try {
    csvFileOutputStream.close();
   } catch (IOException e) {
    e.printStackTrace();
   }
  }
  return csvFile;
 }

 /**
  * 下载文件
  *
  * @param response
  * @param csvFilePath
  *            文件路径
  * @param fileName
  *            文件名称
  * @throws IOException
  */
 public static void exportFile(HttpServletResponse response,
   String csvFilePath, String fileName) throws IOException {
//  response.setHeader("Content-type", "application-download");

  FileInputStream in = null;
  OutputStream out = response.getOutputStream();
  byte[] buffer = new byte[1024];
  int len = 0;
  response.setContentType("text/csv;charset=UTF-8");
  response.setHeader("Content-Disposition", "attachment;filename="
    + URLEncoder.encode(fileName, "UTF-8"));
  response.setCharacterEncoding("UTF-8");
  try {
   in = new FileInputStream(csvFilePath);
   while ((len = in.read(buffer)) > 0) {
    out.write(buffer, 0, len);
   }
   out.flush();
  } catch (FileNotFoundException e) {
   LOG.error("获取文件错误!");
  } finally {
   if (in != null) {
    try {
     in.close();
     out.close();
    } catch (Exception e) {
     throw new RuntimeException(e);
    }
   }
  }
 }

 /**
  * 导出
  *
  * @param response
  * @param fileName
  * @return
  * @throws IOException
  */
 public static void downloadFile(HttpServletRequest request,
   HttpServletResponse response, String uri) throws IOException {
  // 获取服务其上的文件名称
  File file = new File(uri);
  String name = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date())
    + ".zip";
  StringBuffer sb = new StringBuffer();
  sb.append("attachment;  filename=").append(name);
  response.setHeader("Expires", "0");
  response.setHeader("Cache-Control",
    "must-revalidate, post-check=0, pre-check=0");
  response.setHeader("Pragma", "public");
  response.setContentType("application/x-msdownload;charset=UTF-8");
  response.setHeader("Content-Disposition", new String(sb.toString()
    .getBytes(), "ISO8859-1"));

  // 将此文件流写入到response输出流中
  FileInputStream inputStream = new FileInputStream(file);
  OutputStream outputStream = response.getOutputStream();
  byte[] buffer = new byte[1024];
  int i = -1;
  while ((i = inputStream.read(buffer)) != -1) {
   outputStream.write(buffer, 0, i);
  }
  outputStream.flush();
  outputStream.close();
  inputStream.close();
 }

 /**
  * 删除该目录filePath下的所有文件
  *
  * @param filePath
  *            文件目录路径
  */
 public static void deleteFiles(String filePath) {
  File file = new File(filePath);
  if (file.exists()) {
   File[] files = file.listFiles();
   for (int i = 0; i < files.length; i++) {
    if (files[i].isFile()) {
     files[i].delete();
    }
   }
  }
 }

 /**
  * 删除单个文件
  *
  * @param filePath
  *            文件目录路径
  * @param fileName
  *            文件名称
  */
 public static void deleteFile(String filePath, String fileName) {
  File file = new File(filePath);
  if (file.exists()) {
   File[] files = file.listFiles();
   for (int i = 0; i < files.length; i++) {
    if (files[i].isFile()) {
     if (files[i].getName().equals(fileName)) {
      files[i].delete();
      return;
     }
    }
   }
  }
 }

/**
  * 下载csv文件
  * @param path
  * @param response
  */
 private void download(String path, HttpServletResponse response) {
  try {
   // path是指欲下载的文件的路径。
   File file = new File(path);
   // 取得文件名。
   String filename = file.getName();
   // 以流的形式下载文件。
   InputStream fis = new BufferedInputStream(new FileInputStream(path));
   byte[] buffer = new byte[fis.available()];
   fis.read(buffer);
   fis.close();
   // 清空response
   response.reset();
   // 设置response的Header
   response.addHeader("Content-Disposition", "attachment;filename="
     + new String(filename.getBytes()));
   response.addHeader("Content-Length", "" + file.length());
   OutputStream toClient = new BufferedOutputStream(
     response.getOutputStream());
   response.setContentType("application/vnd.ms-excel;charset=gb2312");
   toClient.write(buffer);
   toClient.flush();
   toClient.close();
  } catch (IOException ex) {
   ex.printStackTrace();
  }
 }

 /**
  * 测试数据
  *
  * @param args
  */
 @SuppressWarnings({ "rawtypes", "unchecked" })
 public static void main(String[] args) {
  List exportData = new ArrayList<Map>();
  Map row1 = new LinkedHashMap<String, String>();
  row1 = new LinkedHashMap<String, String>();
  row1.put("1", "11");
  row1.put("2", "12");
  row1.put("3", "13");
  row1.put("4", "14");
  exportData.add(row1);
  row1.put("1", "11");
  row1.put("2", "12");
  row1.put("3", "13");
  row1.put("4", "14");
  exportData.add(row1);
  LinkedHashMap map = new LinkedHashMap();
  map.put("1", "第一列");
  map.put("2", "第二列");
  map.put("3", "第三列");
  map.put("4", "第四列");

  String path = "E:/export/";
  String fileName = "文件导出";
  File file = CsvUtils.createCSVFile(exportData, map, path, fileName);
  String fileName2 = file.getName();
  LOG.debug("文件名称:" + fileName2);
 }

}

         由于在main方法中不能直接调用下载的方法,因此单独创建一个类来完成相关功能,创建类ExportCsvController.java,代码如下

public class ExportCsvController {

 @Autowired
 AccessDetailExportService accessDetailExportService;

 private static final Log LOG = LogFactory.getLog(ExportCsvController.class);

 @RequestMapping(value = "/exportHistory")
 @SuppressWarnings({ "rawtypes", "unchecked", "deprecation" })
 public void exportHistory(HttpServletRequest request,
   HttpServletResponse response, AccessDetailBean accessDetailBean)
   throws IOException {

  HttpSession session = request.getSession();
  UserBean userBean = (UserBean) session.getAttribute("userbean");

  if (!CommonUtil.isAdmin(userBean)) {
   if (userBean == null) {
    throw new RuntimeException("登陆失效,请重新登陆");
   }
   accessDetailBean.setUsername(userBean.getName());
  }
  LOG.debug("-----访问历史监控导出开始-----");
  String realPath = request.getRealPath("/WEB-INF/export"); // 获取绝对路径

   String path = realPath.replace("\\", "/");

  String fileName = "history_"; // 定义文件名称

  List exportData = new ArrayList<Map>();

  Map row = new LinkedHashMap<String, String>();

  LinkedHashMap map = new LinkedHashMap();
  map.put("1", "用户");
  map.put("2", "访问时间");
  map.put("3", "ip");
  map.put("4", "访问的服务");
  map.put("5", "消耗时间(毫秒)");
  map.put("6", "状态");
  map.put("7", "长度");

  int count = accessDetailExportService
    .queryHistoryCount(accessDetailBean);
  LOG.debug("访问历史监控总条数:" + count);

  if (count <= 100000) { // 如果查询总数大于10万条,不予导出
   // 查询访问历史记录
   List<AccessDetailBean> detailList = accessDetailExportService
     .queryHistoryInfo(accessDetailBean);
   LOG.debug("-----访问历史监控数据条数-----" + detailList.size());
   for (AccessDetailBean detail : detailList) { // 执行导出操作
    row = new LinkedHashMap<String, String>();
    row.put("1", detail.getUsername()); // 用户名
    row.put("2", dateConvert(detail.getAccesstime())); // 访问时间
    row.put("3", detail.getClientip()); // 访问ip
    row.put("4", detail.getService()); // 访问的服务
    row.put("5", detail.getCosttime()); // 消耗时间
    row.put("6", statusConvert(detail.getStatus())); // 状态
    row.put("7", detail.getLength()); // 长度
    exportData.add(row);
   }
   File file = CsvUtils.createCSVFile(exportData, map, realPath,
     fileName);
   String fileName2 = file.getName();
   LOG.debug("文件名称:" + fileName2);
   this.download(path + "/" + fileName2, response);
  } else { // 大于10万条不予导出
   CommonUtil.writeResult(response, "记录条数大于10万,导出失败,请添加条件过滤后重试!");
  }
  LOG.debug("-----访问历史监控导出结束-----");
 }

 @RequestMapping(value = "/exportSummary")
 @SuppressWarnings({ "rawtypes", "unchecked", "deprecation" })
 public void exportSummary(HttpServletRequest request,
   HttpServletResponse response,
   AccessDetailSummaryBean accessDetailSummaryBean) throws IOException {

  HttpSession session = request.getSession();
  UserBean userBean = (UserBean) session.getAttribute("userbean");

  if (!CommonUtil.isAdmin(userBean)) {
   if (userBean == null) {
    throw new RuntimeException("登陆失效,请重新登陆");
   }
  }

  LOG.debug("-----访问历史监控导出开始-----");
  String realPath = request.getRealPath("/WEB-INF/export"); // 获取绝对路径
  
  String path = realPath.replace("\\", "/");

  String fileName = "summary_"; // 定义文件名称

  List exportData = new ArrayList<Map>();

  Map row = new LinkedHashMap<String, String>();

  LinkedHashMap map = new LinkedHashMap();
  map.put("1", "访问者");
  map.put("2", "访问的服务");
  map.put("3", "ip");
  map.put("4", "访问key次数");
  map.put("5", "获取数据次数");
  map.put("6", "获取数据成功次数");
  map.put("7", "获取数据失败次数");
  map.put("8", "总次数");
  map.put("9", "数据大小");

  int count = accessDetailExportService
    .querySummaryCount(accessDetailSummaryBean);
  LOG.debug("访问历史统计记录总条数:" + count);

  if (count <= 100000) { // 如果查询总数大于10万条,不予导出
   // 查询访问历史记录
   List<AccessDetailSummaryBean> summaryList = accessDetailExportService
     .querySummaryInfo(accessDetailSummaryBean);
   LOG.debug("-----访问历史监控数据条数-----" + summaryList.size());
   for (AccessDetailSummaryBean summary : summaryList) { // 执行导出操作
    row = new LinkedHashMap<String, String>();
    row.put("1", summary.getVisitor()); // 访问者
    row.put("2", summary.getVisitedServer()); // 访问的服务
    row.put("3", summary.getClientIp()); // ip
    row.put("4", summary.getVisitKeyTime()); // 访问key次数
    row.put("5", summary.getGainDataTime()); // 获取数据次数
    row.put("6", summary.getSuccessTime()); // 获取数据成功次数
    row.put("7", summary.getFailTime()); // 获取数据失败次数
    row.put("8", summary.getSumTime()); // 总次数
    row.put("9", summary.getDataVolume()); // 数据大小
    exportData.add(row);
   }
   File file = CsvUtils.createCSVFile(exportData, map, path, fileName);
   String fileName2 = file.getName();
   LOG.debug("文件名称:" + fileName2);
   this.download(path + "/" + fileName2, response);
  } else { // 大于10万条不予导出
   CommonUtil.writeResult(response, "记录条数大于10万,导出失败,请添加条件过滤后重试!");
  }
  LOG.debug("-----访问历史监控导出结束-----");
 }

 /**
  * 成功失败状态转换
  *
  * @param status
  * @return
  */
 public String statusConvert(Integer status) {
  String flag = null;
  if (status == 0) {
   flag = "成功";
  } else {
   flag = "失败";
  }
  return flag;
 }

 /**
  * 日期格式转换
  *
  * @param date
  * @return
  */
 public String dateConvert(long date) {
  // 设置日期格式
  SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  // 转为日期格式
  Date newDate = new Date(date);
  // 最终日期
  String finalDate = sdf.format(newDate);
  return finalDate;
 }

 /**
  * 下载csv文件
  * @param path
  * @param response
  */
 private void download(String path, HttpServletResponse response) {
  try {
   // path是指欲下载的文件的路径。
   File file = new File(path);
   // 取得文件名。
   String filename = file.getName();
   // 以流的形式下载文件。
   InputStream fis = new BufferedInputStream(new FileInputStream(path));
   byte[] buffer = new byte[fis.available()];
   fis.read(buffer);
   fis.close();
   // 清空response
   response.reset();
   // 设置response的Header
   response.addHeader("Content-Disposition", "attachment;filename="
     + new String(filename.getBytes()));
   response.addHeader("Content-Length", "" + file.length());
   OutputStream toClient = new BufferedOutputStream(
     response.getOutputStream());
   response.setContentType("application/vnd.ms-excel;charset=gb2312");
   toClient.write(buffer);
   toClient.flush();
   toClient.close();
  } catch (IOException ex) {
   ex.printStackTrace();
  }
 }

对于页面可以直接通过jsp+JavaScript来完成:

<a href="javascript:void(0);" class="easyui-linkbutton"
      data-options="iconCls:'icon-save',plain:false"
      onclick="exportHistory();">导出</a>

/**导出访问历史记录*/
 function exportHistory() {
  var username = $('#username').val();
  var accesstimeStart=$('#accesstimeStart').datebox('getValue');
  var accesstimeEnd=$('#accesstimeEnd').datebox('getValue');
  var clientip = $('#clientip').val();
  var service = $('#service').val();
  var status = $('#status').val();
  var costtimeStart = $('#costtimeStart').val();
  var costtimeEnd = $('#costtimeEnd').val();
  window.location.href = $("#proPath").val() + "/export/exportHistory?username=" + username + "&accesstimeStart=" + accesstimeStart +
  "&accesstimeEnd=" + accesstimeEnd + "&clientip=" + clientip + "&service=" + service + "&costtimeStart=" +costtimeStart
  + "&costtimeEnd" + costtimeEnd;
 }

至此一个导出并下载csv文件的功能即实现了。

猜你喜欢

转载自chy0919.iteye.com/blog/2254129