下载csv文件

导出csv格式文件的本质是导出以逗号为分隔的文本数据 ; 

这里使用List<LinkedHashMap<String, Object>> 而不使用List<List<String, Object>> , 

不用申请获取那么多的连续内存!

1. controller:

/**
     * 账单汇总 - 条件导出
     *
     * @param orderCode 检索条件
     * @param billDtStart 检索条件
     * @param billDtEnd 检索条件
     * @param state 检索条件
     * @param corganCodes 检索条件
     * @param status 检索条件
     * @param flag 检索条件
     * @param userNameLike 检索条件
     * @param capitalSide 资金方
     * @param response 相应信息
     */
    @GetMapping("/downloadBillExcel")
    public void downloadBillExcel(@RequestParam(required = false) String orderCode,
                                  @RequestParam(required = false) String billDtStart,
                                  @RequestParam(required = false) String billDtEnd,
                                  @RequestParam(required = false) String state,
                                  @RequestParam(required = false) String corganCodes,
                                  @RequestParam(required = false) String status,
                                  @RequestParam(required = false) String flag,
                                  @RequestParam(required = false) String userNameLike,
                                  @RequestParam(required = false) String capitalSide, HttpServletResponse response,
                                  HttpServletRequest request) {
        UserDto user = UserUtils.getUserByCookie(request);

        if (StringUtils.isBlank(orderCode) && StringUtils.isAnyBlank(billDtStart, billDtEnd)) {
            try {
                response.setContentType("text/html;charset=UTF-8");
                response.getWriter().println("请传入订单编号或账单日期开始时间结束时间!");
                return;
            } catch (Exception e) {
                log.error("Exception:{}", e);
                ExcelUtil.downloadExceptionExcel(response, e);
            }
        }

        PageMapperDto mapperDto = new PageMapperDto();
        mapperDto.setPageStart(null);
        mapperDto.setPageSize(null);
        mapperDto.setUserName(userNameLike);
        mapperDto.setOrderCode(orderCode);
        mapperDto.setCorganCodeListByParam(VehicleUtils.stringToList(corganCodes));
        mapperDto.setFlagList(VehicleUtils.stringToList(flag));
        mapperDto.setStateList(VehicleUtils.stringToList(state));
        mapperDto.setStatusList(VehicleUtils.stringToList(status));
        mapperDto.setCapitalSideList(VehicleUtils.stringToList(capitalSide));
        if (StringUtils.isNotBlank(billDtStart) && StringUtils.isNotBlank(billDtEnd)) {
            mapperDto
                    .setBillDtStart(DateUtils.date2String(DateUtils.parseTimestampToDate(Long.parseLong(billDtStart))));
            mapperDto.setBillDtEnd(DateUtils.date2String(DateUtils.parseTimestampToDate(Long.parseLong(billDtEnd))));
        }
        log.info("条件下载账单信息mapperDto:{}", JSON.toJSON(mapperDto));
        Result<List<String>> organListResult = organService.findOrganCodeListByUserAccount(user, false);
        if (organListResult.isSuccess()) {
            mapperDto.setCorganCodeListByData(organListResult.getValue());
            log.info("数据权限过滤的分公司:{}", mapperDto.getCorganCodeListByData().size());
        }

        orderBillingDownloadService.downloadBillCsv(response, mapperDto);
    }

2. service:

/**
 * 账单信息下载 服务类接口
 *
 * @author zhangshiwei
 * @since 2020年6月18日 下午4:15:37
 */
public interface OrderBillingDownloadService {
    /**
     * 账单汇总 - 下载csv
     *
     * @param response 响应信息
     * @param mapperDto 检索条件
     */
    void downloadBillCsv(HttpServletResponse response, PageMapperDto mapperDto);
}

3. serviceImpl:

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;

import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.yifenqi.common.DateUtils;
import com.yifenqi.zulin.biz.common.constants.YesNoEnum;
import com.yifenqi.zulin.biz.common.dto.PageMapperDto;
import com.yifenqi.zulin.biz.common.util.CsvUtils;
import com.yifenqi.zulin.biz.order.constants.BillFlagEnum;
import com.yifenqi.zulin.biz.order.constants.BillStateEnum;
import com.yifenqi.zulin.biz.order.constants.BillStatusEnum;
import com.yifenqi.zulin.biz.order.constants.OrderConstant;
import com.yifenqi.zulin.biz.order.dto.OrderBillingPageResponseDto;
import com.yifenqi.zulin.biz.order.service.OrderBillingDownloadService;
import com.yifenqi.zulin.biz.vehicle.constants.VehicleConstants;
import com.yifenqi.zulin.component.mybatis.order.OrderBillingMapper;

import lombok.extern.slf4j.Slf4j;

/**
 * 账单下载 服务实现类
 *
 * @author zhangshiwei
 * @since 2020年6月18日 下午4:16:01
 */
@Slf4j
@Service
public class OrderBillingDownloadServiceImpl implements OrderBillingDownloadService {

    @Autowired
    private OrderBillingMapper orderBillingMapper;

    @Value("${file.upload.temp.path}")
    private String             fileDir;

    @Override
    public void downloadBillCsv(HttpServletResponse response, PageMapperDto mapperDto) {
        try {
            List<OrderBillingPageResponseDto> responseDtoList = orderBillingMapper.findOrderBillingPage(mapperDto);
            log.info("downloadBillCsv-账单:{}", responseDtoList.size());

            List<LinkedHashMap<String, Object>> linkedHashMapList = this.dtoListToLinkedHashMapList(responseDtoList);

            CsvUtils.createAndDownloadCSVFile(linkedHashMapList, fileDir, "账单汇总下载", response);
        } catch (Exception e) {
            log.error("Exception:{}", e);
        }
    }

    private List<LinkedHashMap<String, Object>> dtoListToLinkedHashMapList(List<OrderBillingPageResponseDto> responseDtoList) {
        List<LinkedHashMap<String, Object>> exportData = new ArrayList<>(responseDtoList.size());

        String[] titleArray = new String[] { "订单编号", "账单期数", "账单日期", "承租人姓名", "申请时间", "分公司", "分期金额", "应还本金", "应还利息",
                "逾期违约金", "逾期违约罚息", "代扣结果", "资方业务状态", "账单标记", "账单状态", "是否已逾期", "实际还款日期", "已还月租", "已还本金", "已还利息", "已还违约金",
                "已还罚息", "待还月租", "待还本金", "待还利息", "待还违约金", "待还罚息" };

        LinkedHashMap<String, Object> titleData = new LinkedHashMap<>();
        for (int i = 0; i < titleArray.length; i++) {
            titleData.put(String.valueOf(i + 1), titleArray[i]);
        }
        exportData.add(titleData);

        for (OrderBillingPageResponseDto responseDto : responseDtoList) {
            LinkedHashMap<String, Object> rowData = this.dealDataForCsv(responseDto);
            exportData.add(rowData);
        }

        return exportData;
    }

    private LinkedHashMap<String, Object> dealDataForCsv(OrderBillingPageResponseDto responseDto) {
        LinkedHashMap<String, Object> rowData = new LinkedHashMap<>();
        rowData.put("1", responseDto.getOrderCode());
        rowData.put("2", String.valueOf(responseDto.getBillPeriod()));
        rowData.put("3", DateUtils.formatDate(responseDto.getBillDt(), OrderConstant.DATE_FORMAT));
        rowData.put("4", String.valueOf(responseDto.getUserName()));

        if (null != responseDto.getApplyTime()) {
            rowData.put("5", DateUtils.formatDate(responseDto.getApplyTime(), VehicleConstants.TIANYI_TIME_FORMAT));
        }

        rowData.put("6", responseDto.getOrganName());
        rowData.put("7", responseDto.getBillFee());
        rowData.put("8", responseDto.getBillCapital());
        rowData.put("9", responseDto.getBillInterest());
        rowData.put("10", responseDto.getOverdueContractAmt());
        rowData.put("11", responseDto.getOverduePenalty());
        rowData.put("12", responseDto.getWithholdResult());

        BillStateEnum billStateEnum = BillStateEnum.getEnumByCode(responseDto.getState());
        if (billStateEnum != null) {
            rowData.put("13", billStateEnum.getMsg());
        }

        BillFlagEnum billFlagEnum = BillFlagEnum.getEnumByCode(responseDto.getFlag());
        if (billFlagEnum != null) {
            rowData.put("14", billFlagEnum.getMsg());
        }

        BillStatusEnum billStatusEnum = BillStatusEnum.getEnumByCode(responseDto.getStatus());
        if (billStatusEnum != null) {
            rowData.put("15", billStatusEnum.getMsg());
        }

        YesNoEnum yesNoEnum = YesNoEnum.getEnumByCode(responseDto.getIsOverdue());
        if (yesNoEnum != null) {
            rowData.put("16", yesNoEnum.getMsg());
        }

        if (null != responseDto.getBillRepayDt()) {
            rowData.put("17", DateUtils.formatDate(responseDto.getBillRepayDt(), OrderConstant.DATE_FORMAT));
        }

        rowData.put("18", responseDto.getPaidFee());
        rowData.put("19", responseDto.getBillCapital().subtract(responseDto.getUnpaidCapital()));
        rowData.put("20", responseDto.getBillInterest().subtract(responseDto.getUnpaidIntrest()));
        rowData.put("21", responseDto.getOverdueContractAmt().subtract(responseDto.getUnpaidContractAmt()));
        rowData.put("22", responseDto.getOverduePenalty().subtract(responseDto.getUnpaidPenalty()));
        rowData.put("23", responseDto.getUnpaidFee());
        rowData.put("24", responseDto.getUnpaidCapital());
        rowData.put("25", responseDto.getUnpaidIntrest());
        rowData.put("26", responseDto.getUnpaidContractAmt());
        rowData.put("27", responseDto.getUnpaidPenalty());

        return rowData;
    }
}

4. 工具类:

import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.URLEncoder;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map.Entry;

import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.springframework.util.CollectionUtils;
import org.springframework.util.FileCopyUtils;

import lombok.extern.slf4j.Slf4j;

/**
 * CSV文件工具类
 *
 * @author zhangshiwei
 * @since 2020-06-11 16:11:12
 */
@Slf4j
public class CsvUtils {

    /**
     * CSV文件生成并下载
     *
     * @param dataList 数据列表
     * @param fileDir 文件目录
     * @param fileName 文件名
     * @param response 响应信息
     */
    public static void createAndDownloadCSVFile(List<LinkedHashMap<String, Object>> dataList, String fileDir,
                                                String fileName, HttpServletResponse response) {
        if (CollectionUtils.isEmpty(dataList) || StringUtils.isAnyBlank(fileDir, fileName) || null == response) {
            return;
        }

        BufferedWriter csvWriter = null;
        try {
            response.setHeader("Charset", "UTF-8");
            response.setHeader("Content-Type", "application/force-download");
            response.setHeader("Content-Type", "application/vnd.ms-excel");
            response.setHeader("Content-disposition",
                    "attachment; filename=" + URLEncoder.encode(fileName, "utf8") + ".csv");
            response.flushBuffer();
            OutputStream outputStream = response.getOutputStream();

            File csvFile = new File(fileDir + File.separator + fileName + ".csv");

            File parent = csvFile.getParentFile();
            if (parent != null && !parent.exists()) {
                boolean mkdirsResult = parent.mkdirs();
                log.info("mkdirsResult:{}", mkdirsResult);
            }
            boolean createNewFileResult = csvFile.createNewFile();
            log.info("createNewFileResult:{}", createNewFileResult);

            // GB2312使正确读取分隔符","
            csvWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(csvFile), "GB2312"), 1024);

            // 写入文件内容
            for (LinkedHashMap<String, Object> linkedHashMap : dataList) {
                Iterator<Entry<String, Object>> iterator = linkedHashMap.entrySet().iterator();
                while (iterator.hasNext()) {
                    Entry<String, Object> entry = iterator.next();
                    String rowStr = String.format("%s%s%s", "\"", entry.getValue(), "\",");
                    csvWriter.write(rowStr);
                }
                csvWriter.newLine();
            }

            csvWriter.flush();

            byte[] buffer = CsvUtils.getFileByteArray(csvFile);
            if (null != buffer) {
                FileCopyUtils.copy(buffer, outputStream);
            }

            boolean deleteResult = csvFile.delete();
            log.info("deleteResult is{}", deleteResult);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (null != csvWriter) {
                    csvWriter.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 获取文件字节流
     *
     * @param file 文件信息
     * @return 字节流
     */
    public static byte[] getFileByteArray(File file) {
        if (null == file) {
            return null;
        }

        byte[] buffer = null;
        FileInputStream fis;
        try {
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            fis = new FileInputStream(file);
            byte[] b = new byte[1024];
            int n;
            while ((n = fis.read(b)) != -1) {
                bos.write(b, 0, n);
            }
            fis.close();
            bos.close();
            buffer = bos.toByteArray();
            if (file.exists()) {
                boolean deleteResult = file.delete();
                log.info("getFileByteArray deleteResult:{}", deleteResult);
            }
        } catch (Exception e) {
            log.info("getFileByteArray Exception:{}", e);
        }
        return buffer;
    }

}

6. 使用poi包下载excel文件很方便,但是内部数据格式是设置好的,只能按照jar要求的格式来,除非将相关代码copy一套再修改,否则每次请求都是需要很多的连续内存.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章