下載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一套再修改,否則每次請求都是需要很多的連續內存.

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