Generic Asynchronous Threads Download zip Packets and Export excel Files

Keywords: Excel Mobile

Generic Asynchronous Threads Download zip Packets and Export excel Files

Preface: The page clicks the download button (export excel file in batches and export in zip package format). It uses asynchronous thread to query data, encapsulate excel and export the download process.

  • General class of file export template

To extract an abstract class, generics inherit from the derived parameter model base class, so that different types of file can be exported easily, only need to change the input type (need to inherit the basic model class). Generate general abstract methods, generate input parameters, query parameters, generate files, download files, import external systems (DFS), etc.

/**
 * General class of file export template
 *
 * @author Hang.W
 * @date 2019-08-26 16:18
 */
@Slf4j
public abstract class AbstractDownloadTemplate<T extends MctProdBaseReqDTO> {

	/** dfs Tool class */
    @Autowired
    private DfsFileDealUtils dfsFileDealUtils;

	/** Download Center */
    @Autowired
    private MctProdReserveDownloadManager mctProdReserveDownloadManager;

    /**
     * Generate export file parameters and record Downloads
	 *
     * @param request
     * @return
     */
    public abstract MctCoreDownloadTaskInsertReqDTO insertRecord(T request);

    /**
     * Query data
	 *
     * @param request
     * @return
     */
    public abstract Object queryDate(T request) throws Exception;

    /**
     * Generate files
	 *
     * @param o
     * @return
     */
    public abstract byte[] generateFile(T request, Object o, Object oj) throws Exception;

    /**
     * Download method
     * @param request
     * @param fileType
     */
    public void download(T request, MctCoreDownloadTaskInsertReqDTO downloadTaskInsertReqDTO,
                         String fileType) {
        DownLoadThread<T> downLoadThread = new DownLoadThread<>(this, request,
            downloadTaskInsertReqDTO, fileType, null);
        ThreadPoolUtils.execute(downLoadThread);
    }

    /**
     * Download method
	 *
     * @param request
     * @param fileType
     */
    public void download(T request, MctCoreDownloadTaskInsertReqDTO downloadTaskInsertReqDTO,
                         String fileType, Object o) {
        DownLoadThread<T> downLoadThread = new DownLoadThread<>(this, request,
            downloadTaskInsertReqDTO, fileType, o);
        ThreadPoolUtils.execute(downLoadThread);
    }

    /**
     * Complete File Upload Extranet
	 *
     * @param t Request data
     * @param fileFormat file format
     */
    public void finishDownload(T t, MctCoreDownloadTaskInsertReqDTO downloadTaskInsertReqDTO,
                               String fileFormat, Object o) {
        try {
            byte[] fileByte = generateFile(t, queryDate(t), o);
            String filePath = dfsFileDealUtils.uploadFileByBytes(fileByte, fileFormat);
            if (filePath != null) {
                downloadTaskInsertReqDTO.setFileFullPath(MctProdConstant.DFS_HTTP_PATH + filePath);
                downloadTaskInsertReqDTO
                    .setStatus(MctCoreFileDownloadTaskStatusEnum.SUCCESS.getCode());
                downloadTaskInsertReqDTO.setUpdatedAt(new Date());
                mctProdReserveDownloadManager.initOrUpdateDownloadTask(downloadTaskInsertReqDTO);
            } else {
                downloadTaskInsertReqDTO
                    .setStatus(MctCoreFileDownloadTaskStatusEnum.FAILURE.getCode());
                downloadTaskInsertReqDTO.setUpdatedAt(new Date());
                mctProdReserveDownloadManager.initOrUpdateDownloadTask(downloadTaskInsertReqDTO);
            }
        } catch (Exception e) {
            log.info("File upload extranet is abnormal, the reason is:{}", downloadTaskInsertReqDTO, e);
            downloadTaskInsertReqDTO.setStatus(MctCoreFileDownloadTaskStatusEnum.FAILURE.getCode());
            downloadTaskInsertReqDTO.setUpdatedAt(new Date());
            mctProdReserveDownloadManager.initOrUpdateDownloadTask(downloadTaskInsertReqDTO);
        }
    }
	
}
  • Specific file download class, inherited from generic template download class
  1. Inherited from the above generic template download class, override the method of generating input parameters and generating files.
  2. Involve the MctProdExportStoreReqDTO portal export class, generics inherit from the underlying model class.
  3. In the method of generating excel file, POI creates HSSFWorkbook, excel, including merging cells, font color, etc., and finally generates and imports into zip package.
/**
 * Portal information export Excel form zip package format
 *
 * @author Hang.W
 * @date 2019-08-26 16:24
 */
@Slf4j
@Service
public class MctProdExportStoreInfoExcelProcess extends AbstractDownloadTemplate<MctProdExportStoreReqDTO> {

	/** Download Center Table */
    @Autowired
    private MctCoreDownloadTaskService mctCoreDownloadTaskService;

    @Autowired
    private SequenceUtils sequenceUtils;

    @Autowired
    private MctProdMerchantInfoManager mctProdMerchantInfoManager;

    @Override
    public MctCoreDownloadTaskInsertReqDTO insertRecord(MctProdExportStoreReqDTO reqDTO) {
        MctCoreDownloadTaskInsertReqDTO downloadTaskInsertReqDTO = new MctCoreDownloadTaskInsertReqDTO();
        downloadTaskInsertReqDTO.setMerchantCode(reqDTO.getMerchantCode());
        downloadTaskInsertReqDTO.setFileId(sequenceUtils.getSequenceNo());
        downloadTaskInsertReqDTO.setFileType(MctCoreFileDownloadTypeEnum.MERCHANT_STORE_INFO.getCode());
        downloadTaskInsertReqDTO.setFileName(reqDTO.getMerchantCode() + "_Business Portal Information" + ".zip");
        downloadTaskInsertReqDTO.setFileFullPath("");
        downloadTaskInsertReqDTO.setStatus(MctCoreFileDownloadTaskStatusEnum.DOING.getCode());
        downloadTaskInsertReqDTO.setRemark("");
        downloadTaskInsertReqDTO.setCreatedAt(new Date());
        downloadTaskInsertReqDTO.setCreatedBy(reqDTO.getMerchantCode());
        downloadTaskInsertReqDTO.setTraceLogId(reqDTO.getTraceLogId());

        Result<Boolean> response = mctCoreDownloadTaskService.insertDownloadTask(downloadTaskInsertReqDTO);
        if (response.isSuccess() && response.getResult()) {
            return downloadTaskInsertReqDTO;
        } else {
            return null;
        }
    }

    @Override
    public Object queryDate(MctProdExportStoreReqDTO request) throws Exception {
        return null;
    }

    @Override
    public byte[] generateFile(MctProdExportStoreReqDTO mctProdExportStoreReqDTO, Object o, Object oj) throws Exception {

        log.info("MctProdMerchantInfoServiceImpl.exportStore Portal Information Export Excel form, Participation{}", mctProdExportStoreReqDTO);
        Result<List<MctCoreStoreInfoResDTO>> result = mctProdMerchantInfoManager.exportStore(mctProdExportStoreReqDTO);
        log.info("MctProdMerchantInfoServiceImpl.exportStore Portal Information Export Excel form, Return{}", result);
        if(!result.isSuccess() || null == result.getResult()) {
            log.error("MctProdMerchantInfoManager.exportStore Call the core according to the business name merchantCode Full query for portal information failed:{}", result);
            throw new MerchantProductBizException(BizErrorCode.EMPTY_QUERY_RESULT, result.getErrorMsg());
        }

        HSSFWorkbook workbook = new HSSFWorkbook();
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        // Compressed output stream
        ZipOutputStream zipOut = new ZipOutputStream(baos);

        try {
            HSSFSheet sheet = workbook.createSheet("Portal information");
            sheet.setColumnWidth(0, 30 * 256);
            sheet.setColumnWidth(1, 30 * 256);
            sheet.setColumnWidth(2, 50 * 256);
            sheet.setColumnWidth(3, 30 * 256);
            sheet.setColumnWidth(4, 30 * 256);
            sheet.setColumnWidth(5, 30 * 256);
            sheet.setColumnWidth(6, 30 * 256);
            sheet.setColumnWidth(7, 50 * 256);
            sheet.setColumnWidth(8, 30 * 256);
            sheet.setColumnWidth(9, 30 * 256);

            // Setting font color
            HSSFFont font = workbook.createFont();
            font.setColor(HSSFColor.RED.index);
            HSSFCellStyle redFontStyle = workbook.createCellStyle();
            redFontStyle.setFont(font);

            HSSFRow row0 = sheet.createRow(0);
            HSSFCell cell0 = row0.createCell(0);
            cell0.setCellValue("Fill in the instructions (please keep 1 when filling in the information)-5 Line, delete line 6)");
            cell0.setCellStyle(redFontStyle);
            CellRangeAddress region0 = new CellRangeAddress(0, 0, 0, 9);
            sheet.addMergedRegion(region0);
            HSSFRow row1 = sheet.createRow(1);
            row1.createCell(0).setCellValue("1,Red font is required. Please fill in according to the standard.");
            CellRangeAddress region1 = new CellRangeAddress(1, 1, 0, 9);
            sheet.addMergedRegion(region1);
            HSSFRow row2 = sheet.createRow(2);
            row2.createCell(0).setCellValue("2,Telephone support cell phone number and landline two kinds, as long as one can be input, fixed telephone please add area code, such as: 010-12345678,Mobile phone numbers are usually 11 digits");
            CellRangeAddress region2 = new CellRangeAddress(2, 2, 0, 6);
            sheet.addMergedRegion(region2);
            HSSFRow row3 = sheet.createRow(3);
            row3.createCell(0).setCellValue("3,Name of the same business portal/Detailed Address Not Repeatable");
            CellRangeAddress region3 = new CellRangeAddress(3, 3, 0, 1);
            sheet.addMergedRegion(region3);

            HSSFRow row = sheet.createRow(4);
            HSSFCell cell4_0 = row.createCell(0);
            cell4_0.setCellValue("Portal name");
            cell4_0.setCellStyle(redFontStyle);
            HSSFCell cell4_1 = row.createCell(1);
            cell4_1.setCellValue("Portal number");
            cell4_1.setCellStyle(redFontStyle);
            row.createCell(2).setCellValue("Branch name");
            HSSFCell cell4_3 = row.createCell(3);
            cell4_3.setCellValue("Portal attributes");
            cell4_3.setCellStyle(redFontStyle);
            HSSFCell cell4_4 = row.createCell(4);
            cell4_4.setCellValue("Province");
            cell4_4.setCellStyle(redFontStyle);
            HSSFCell cell4_5 = row.createCell(5);
            cell4_5.setCellValue("City");
            cell4_5.setCellStyle(redFontStyle);
            HSSFCell cell4_6 = row.createCell(6);
            cell4_6.setCellValue("District and county");
            cell4_6.setCellStyle(redFontStyle);
            HSSFCell cell4_7 = row.createCell(7);
            cell4_7.setCellValue("Detailed address");
            cell4_7.setCellStyle(redFontStyle);
            HSSFCell cell4_8 = row.createCell(8);
            cell4_8.setCellValue("Contacts");
            cell4_8.setCellStyle(redFontStyle);
            HSSFCell cell4_9 = row.createCell(9);
            cell4_9.setCellValue("Telephone");
            cell4_9.setCellStyle(redFontStyle);

            int rowCount = 4;
            for (MctCoreStoreInfoResDTO mctCoreStoreInfoResDTO : result.getResult()) {
                rowCount++;
                row = sheet.createRow(rowCount);
                row.createCell(0).setCellValue(mctCoreStoreInfoResDTO.getStoreName());
                row.createCell(1).setCellValue(mctCoreStoreInfoResDTO.getStoreNo());
                row.createCell(2).setCellValue(mctCoreStoreInfoResDTO.getSubStoreName());
                row.createCell(3).setCellValue(mctCoreStoreInfoResDTO.getStoreType());
                row.createCell(4).setCellValue(mctCoreStoreInfoResDTO.getProvinceCode());
                row.createCell(5).setCellValue(mctCoreStoreInfoResDTO.getCityCode());
                row.createCell(6).setCellValue(mctCoreStoreInfoResDTO.getAreaCode());
                row.createCell(7).setCellValue(mctCoreStoreInfoResDTO.getAddress());
                row.createCell(8).setCellValue(mctCoreStoreInfoResDTO.getLinkMan());
                row.createCell(9).setCellValue(mctCoreStoreInfoResDTO.getTelephone());
            }

            // The formatting is text
            HSSFCellStyle style = workbook.createCellStyle();
            style.setDataFormat(workbook.createDataFormat().getFormat("yyyy-mm-dd"));
            sheet.setDefaultColumnStyle(0, style);
            sheet.setDefaultColumnStyle(1, style);
            sheet.setDefaultColumnStyle(2, style);
            sheet.setDefaultColumnStyle(3, style);
            sheet.setDefaultColumnStyle(4, style);
            sheet.setDefaultColumnStyle(5, style);
            sheet.setDefaultColumnStyle(6, style);
            sheet.setDefaultColumnStyle(7, style);
            sheet.setDefaultColumnStyle(8, style);
            sheet.setDefaultColumnStyle(9, style);
            log.info("Full Export Portal Information zip Pack Start");
            // Compressed storage
            zipOut.setMethod(ZipOutputStream.DEFLATED);
            // Compression level value is 0-9, a total of 10 levels (the larger the value, the more severe the compression)
            zipOut.setLevel(Deflater.BEST_COMPRESSION);
            // Name files that need to be compressed
            zipOut.putNextEntry(new ZipEntry("Business Portal Information.xls"));
            // Read the byte output stream to be compressed and compress it
            workbook.write(zipOut);
            zipOut.flush();

        } catch (IOException e) {
            log.error("Export portal information in full and write exception information:{}, {}", e.getMessage(), e);
            throw new RuntimeException(e);
        } finally {
            workbook.close();
            baos.close();
            zipOut.close();
        }
        log.info("Full Export Portal Information zip Package completion");
        return baos.toByteArray();
    }

}

 

  • Document export steps
  1. Create interface to download files
  2. Use specific file to download classes, invoke methods, generate downloaded files for reference, and invoke downloaded file methods to start downloading files.
/**
 * Asynchronous file export class
 *
 * @author Hang.W
 * @date 2019-08-26 16:37
 */
@Service
@Slf4j
public class MctProdMerchantInfoServiceImpl implements MctProdMerchantInfoService {

    @Autowired
    private MctProdExportStoreInfoExcelProcess mctProdExportStoreInfoExcelProcess;

	/**
	 * Export portal information
	 */
    @Override
    public Result<Boolean> exportStore(MctProdExportStoreReqDTO mctProdExportStoreReqDTO) {
        MDC.put(Marker.TRACE_LOG_ID, mctProdExportStoreReqDTO.getTraceLogId());
        Result<Boolean> result = new Result<>(Boolean.FALSE);
        try {
            log.info("MctProdMerchantInfoServiceImpl.exportStore Portal Information Export Excel form, Participation{}", mctProdExportStoreReqDTO);
			// Encapsulate and export excel parameters
            MctCoreDownloadTaskInsertReqDTO mctCoreDownloadTaskInsertReqDTO = mctProdExportStoreInfoExcelProcess
                    .insertRecord(mctProdExportStoreReqDTO);

            if (mctCoreDownloadTaskInsertReqDTO != null) {
				// Execute export excel operation
                mctProdExportStoreInfoExcelProcess.download(mctProdExportStoreReqDTO,
                        mctCoreDownloadTaskInsertReqDTO, "zip");
                result.setResult(Boolean.TRUE);
                log.info("MctProdMerchantInfoServiceImpl.exportStore Portal Information Export Excel Form Successful");
            }
        } catch (Exception e) {
            log.error("MctProdMerchantInfoServiceImpl.exportStore Portal Information Export Excel form, abnormal{}", e);
            result = DealExceptionUtil.doExceptionService(e);
        }
        return result;
    }

}
  • Asynchronous threads start downloading files
  1. Specific file download implementation class does not override the generic template download method, so use the generic template download method
  2. In the general template download class, create threads to realize the function of uploading first and then downloading.
  3. Thread class construction method imports reference, generic template class for downloading different types of file objects
/**
 * Asynchronous Thread Download
 *
 * @author Hang.W
 * @date 2019-08-26 16:53
 */
public class DownLoadThread<T extends MctProdBaseReqDTO> implements Runnable {

    private AbstractDownloadTemplate<T> abstractDownloadTemplate;

    private MctCoreDownloadTaskInsertReqDTO downloadTaskInsertReqDTO;
	
	private T request;

    private Object o;
	
	private String fileFormat;

    public DownLoadThread(AbstractDownloadTemplate<T> abstractDownloadTemplate, T request,
                          MctCoreDownloadTaskInsertReqDTO downloadTaskInsertReqDTO,
                          String fileFormat, Object o) {
        this.abstractDownloadTemplate = abstractDownloadTemplate;
        this.request = request;
        this.downloadTaskInsertReqDTO = downloadTaskInsertReqDTO;
        this.fileFormat = fileFormat;
        this.o = o;
    }

    @Override
    public void run() {
         abstractDownloadTemplate.finishDownload(request, downloadTaskInsertReqDTO, fileFormat, o);
    }
	
}
  • Specific portal model classes
/**
 * Portal Model Class
 *
 * @author Hang.W
 * @date 2019-08-26 17:05
 */
@Getter
@Setter
@ToString
public class MctProdExportStoreReqDTO extends MctProdBaseReqDTO {

	/** Portal number */
    @NotBlank(message = "The portal number cannot be empty")
    @NotNull(message = "The portal number cannot be empty")
    private String storeCode;

}
  • summary
  1. Extract generic template file download classes
  2. For different file objects, such as user information, product information, capital information, etc., different input, different implementations of the same kind can be used to perform functions.
  3. This article includes the generation of excel and the download of zip

 

Posted by collamack on Mon, 26 Aug 2019 02:54:17 -0700