package com.sunxung.factoring.service.purchcontractmanagement.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sunxung.factoring.component.exception.BusinessException;
import com.sunxung.factoring.component.exception.ValidatorException;
import com.sunxung.factoring.component.util.*;
import com.sunxung.factoring.dict.impl.FileModuleDict;
import com.sunxung.factoring.dict.impl.ProjectInitiationStatusDict;
import com.sunxung.factoring.dict.impl.PurchContractStatusDict;
import com.sunxung.factoring.entity.businessmanagement.BusinessBasicInfo;
import com.sunxung.factoring.entity.customerinformation.Customer;
import com.sunxung.factoring.entity.purchcontractmanagement.*;
import com.sunxung.factoring.entity.sys.Dictionary;
import com.sunxung.factoring.entity.sys.FileStorage;
import com.sunxung.factoring.entity.tradingPlatform.Platform;
import com.sunxung.factoring.mapper.purchcontractmanagement.PurchContractSignApprovalMapper;
import com.sunxung.factoring.service.businessmanagement.BusinessBasicInfoService;
import com.sunxung.factoring.service.businessmanagement.BusinessSupplierInfoService;
import com.sunxung.factoring.service.customerinformation.CustomerService;
import com.sunxung.factoring.service.purchcontractmanagement.*;
import com.sunxung.factoring.service.salescontractmanagement.SalesContractGoodsInfoService;
import com.sunxung.factoring.service.sys.DictionaryService;
import com.sunxung.factoring.service.sys.FileStorageService;
import com.sunxung.factoring.service.sys.ISysAttachmentRefService;
import com.sunxung.factoring.service.sys.dto.AttachmentDto;
import com.sunxung.factoring.service.sys.flowable.FlowableService;
import com.sunxung.factoring.service.tradingPlatform.PlatformService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import static com.sunxung.factoring.dict.impl.FileModuleDict.ChildEnum.PURCHASE_CONTRACT_FILE;

/**
 * <p>
 * 采购合同-签署审核表 服务实现类
 * </p>
 *
 * @author daxian
 * @since 2022-03-14
 */
@Service("purch_contract_final_approvalService")
public class PurchContractSignApprovalServiceImpl extends ServiceImpl<PurchContractSignApprovalMapper, PurchContractSignApproval> implements IPurchContractSignApprovalService {

    @Autowired
    private PurchContractService purchContractService;

    @Autowired
    private PurchContractBasicInfoService purchContractBasicInfoService;

    @Autowired
    private BusinessBasicInfoService businessBasicInfoService;

    @Autowired
    private FileStorageService fileStorageService;

    @Autowired
    private FlowableService flowableService;

    @Autowired
    private DictionaryService dictService;

    @Autowired
    private PlatformService platformService;

    @Autowired
    private BusinessSupplierInfoService businessSupplierInfoService;

    @Autowired
    private CustomerService customerService;

    @Autowired
    private PurchContractGoodsInfoService purchContractGoodsInfoService;

    @Autowired
    private SalesContractGoodsInfoService salesContractGoodsInfoService;

    @Autowired
    private PurchContractReplenishInfoService purchContractReplenishInfoService;

    @Autowired
    private PurchContractQualityAcceptService purchContractQualityAcceptService;

    @Autowired
    private PurchContractSettlePaymentService purchContractSettlePaymentService;

    @Autowired
    private IPurchContractApprovalSettlePaymentService purchContractApprovalSettlePaymentService;

    @Autowired
    private PurchContractDeliverClauseService purchContractDeliverClauseService;

    @Autowired
    private PurchContractSellerBlameService purchContractSellerBlameService;

    @Autowired
    private PurchContractPunishClauseService purchContractPunishClauseService;

    @Autowired
    private PurchContractOtherClauseService purchContractOtherClauseService;

    @Autowired
    private PurchContractApprovalService purchContractApprovalService;

    @Autowired
    private ISysAttachmentRefService attachmentRefService;

    @Override
    public PurchContractSignApproval getView(Long id) {
        PurchContractSignApproval purchContractSignApproval = baseMapper.selectById(id);
        if (purchContractSignApproval == null) {
            throw new BusinessException(CodeUtil.FAIL, "获取不到对应采购合同签署信息");
        }

        PurchContractBasicInfo purch = purchContractBasicInfoService.getById(purchContractSignApproval.getPurchContractBasicInfoId());
        if(purch != null && purch.getId() != null){
            List<FileStorage> fileStorageList = new ArrayList<>();
            fileStorageList.addAll(attachmentRefService.getFiles(AttachmentDto.builder().setChildEnum(FileModuleDict.ChildEnum.PURCHASE_CONTRACT_SIGN_FILE).setEntityId(purch.getId()).build()));
            purchContractSignApproval.setFileStorageList(fileStorageList);
        }

        return purchContractSignApproval;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void audit(PurchContractSignApproval purchContractFinalApproval, Long businessKey, String taskId) {
        if (purchContractFinalApproval == null || businessKey == null) {
            throw new ValidatorException(CodeUtil.FAIL, "审核信息或者业务id不能为空");
        }

        PurchContractManagement purchContractManagement = purchContractService.getById(businessKey);
        if (purchContractManagement == null) {
            throw new BusinessException(CodeUtil.FAIL, "获取不到对应采购合同管理信息");
        }

        PurchContractBasicInfo purch = purchContractBasicInfoService
                .lambdaQuery().eq(PurchContractBasicInfo::getPurchContractManagementId, purchContractManagement.getId()).one();

        if (purch == null) {
            throw new BusinessException(CodeUtil.FAIL, "获取不到对应采购合同信息");
        }

        purchContractFinalApproval.setAuditorId(ThreadLocalUtil.getUserId());
        purchContractFinalApproval.setPurchContractBasicInfoId(purch.getId());
        baseMapper.insert(purchContractFinalApproval);

        String result = null;

        if(purchContractFinalApproval.getApprovalConclusion().equals(ConstantConversionUtil.APPROVAL_RESULT_PASS)
        || purchContractFinalApproval.getApprovalConclusion().equals(ConstantConversionUtil.APPROVAL_RESULT_VETO)){
            result = ConstantConversionUtil.APPROVAL_RESULT_PASS_DISPLAY;
        }else if(purchContractFinalApproval.getApprovalConclusion().equals(ConstantConversionUtil.APPROVAL_RESULT_BACK)) {
            result = ConstantConversionUtil.APPROVAL_RESULT_BACK_DISPLAY;
        }else {
            throw new ValidatorException(CodeUtil.FAIL,"结论有误，无法提交！！");
        }

        Map<String, Object> procVariables = new HashMap<>();
        procVariables.put("result",result);
        //流程处理
        String processKey = ConstantUtil.PURCH_CONTRACT;

        Map<String, Object> msgVariables = new HashMap<>(2);

        msgVariables.put(ConstantUtil.FLOWABLE_MSG_TITLE, purch.getProjectName());
        msgVariables.put(ConstantUtil.FLOWABLE_MSG_CONTENT,
                "业务编号为" + purchContractManagement.getBusinessNumber() + "”的项目已inOut“"
                        + ConstantConversionUtil.flowBusinessKeyNames.get(processKey) + "—formBusiness”阶段，");
        Boolean success = flowableService.completeMyTask(taskId, purchContractManagement, procVariables,
                null,
                purchContractFinalApproval.getId(), msgVariables, processKey);
        if (success == null || !success) {
            throw new ValidatorException(CodeUtil.FAIL, "采购合同签署审批出错啦！");
        }

        //如果审核结论为通过、修改合同状态为已确认
        if (purchContractFinalApproval.getApprovalConclusion().equals(ConstantConversionUtil.APPROVAL_RESULT_PASS)) {
            purchContractManagement.setContractStatus(ProjectInitiationStatusDict.ChildEnum.COMPLETED.getCode());
        }
        //如果审核结论为否决、修改合同状态为已终止
        if (purchContractFinalApproval.getApprovalConclusion().equals(ConstantConversionUtil.APPROVAL_RESULT_VETO)) {
            purchContractManagement.setContractStatus(ProjectInitiationStatusDict.ChildEnum.TERMINATED.getCode());
        }
        //如果审核结论为退回、修改合同状态为已审核
//        if (purchContractFinalApproval.getApprovalConclusion().equals(ConstantConversionUtil.APPROVAL_RESULT_BACK)) {
//            purchContractManagement.setContractStatus(firstApprovalDict.getId());
//        }
        purchContractService.updateById(purchContractManagement);
    }

    @Override
    public List<FileStorage> priviewPurchContract(String businessKey, String taskId, HttpServletRequest request, HttpServletResponse response) {
        PurchContractManagement purchContractManagement = purchContractService.getById(businessKey);

        PurchContractBasicInfo purch = purchContractBasicInfoService
                .lambdaQuery().eq(PurchContractBasicInfo::getPurchContractManagementId, purchContractManagement.getId()).one();

        // 每次进来 先删除掉之前预览过的附件
        purchContractBasicInfoService.deleteFileByPurchContractId(purch.getId());
        List<FileStorage> fileStorageList = new ArrayList<>();
        List<File> list = createPurchContractDocument(purchContractManagement, purch, taskId, request, response);
        if (null != list && list.size() > 0) {
            for (File file : list) {
                // 原文件名称
                String originalName = file.getName();
                FileStorage fileStorage = new FileStorage(originalName, file.getAbsolutePath(),
                        PURCHASE_CONTRACT_FILE);
                fileStorageService.add(fileStorage);
                purchContractBasicInfoService.addFileRef(purch.getId(), fileStorage.getId());
                fileStorageList.add(fileStorage);
            }
        }
        return fileStorageList;
    }

    /**
     * 生成合同
     *
     * @param purchContractManagement
     * @param purch
     * @param taskId
     * @param request
     * @param response
     * @return List<File>
     */
    public List<File> createPurchContractDocument(PurchContractManagement purchContractManagement, PurchContractBasicInfo purch, String taskId, HttpServletRequest request, HttpServletResponse response) {
        List<File> list = new ArrayList<>();
        try {
        XMlToDoc xmlDoc = new XMlToDoc();
        dealPurchContractDownload(purchContractManagement, purch, list, xmlDoc);
        } catch (Exception e) {
            throw new BusinessException(CodeUtil.FAIL, "生成合同出错");
        }
        return list;
    }

    /**
     * 下载采购合同信息
     */
    public void dealPurchContractDownload(PurchContractManagement purchContractManagement, PurchContractBasicInfo purch, List<File> list, XMlToDoc xmlDoc) {
        try {
            Map<String, Object> dataMap = new HashMap<>();
            // 合同名称
            String contractName = purch.getContractName();

            //合同模板数据填充 开始
            //获取对应的业务信息
            BusinessBasicInfo businessBasicInfo = businessBasicInfoService.getByBusinessNumber(purchContractManagement.getBusinessNumber());
            //获取平台信息
            Platform platform =platformService.getById(businessBasicInfo.getTradingPlatformId());

            //获取对应供货商的企业客户信息
            Customer supplierCustomer = customerService.getById(purchContractManagement.getSupplierId());
            //获取业务买方对应的企业客户信息
            Customer purchaserCustomer =  customerService.getById(businessBasicInfo.getEnterpriseCustomerInfoId());

            //合同名称
            dataMap.put("contractName", contractName);
            //合同编号
            dataMap.put("contractNumber", purch.getContractNumber());
            //签订日期  暂时给null，后边需处理
            dataMap.put("signDate", null);
            //需方公司名称
            dataMap.put("platformName", platform.getPlatformName());
            //需方统一社会信用代码
            dataMap.put("platformSocialCreditCode", platform.getSocialCreditCode());
            //供货公司名称
            dataMap.put("supplierName", supplierCustomer.getEnterpriseName());
            //供应商统一社会信用代码
            dataMap.put("supplierSocialCreditCode", supplierCustomer.getSocialCreditCode());
            //买方名称
            dataMap.put("purchaserName", purchaserCustomer.getEnterpriseName());
            //业务名称
            dataMap.put("businessName", businessBasicInfo.getName());

            //交易标的物  开始
            List<Map<String, Object>> dealGoodsList = new ArrayList<>();
            //获取货物信息
            List<PurchContractGoodsInfo> purchGoodsList = purchContractGoodsInfoService.lambdaQuery().eq(PurchContractGoodsInfo::getPurchContractBasicInfoId,purch.getId()).list();
            for (PurchContractGoodsInfo purchGoods : purchGoodsList){
                Map<String, Object> gMap = new HashMap<>();
               //序号
//                gMap.put("goodsCode", purchGoods.getGoodsCode());
                //材料名称
                gMap.put("goodsName", purchGoods.getGoodsName());
                //规格型号
                gMap.put("modelNumber", purchGoods.getModelNumber());
                //生产厂家
                gMap.put("goodsFactory", purchGoods.getGoodsFactory());
                //计量单位
                gMap.put("Units", purchGoods.getUnits());
                //数量
                gMap.put("quantity", purchGoods.getQuantity());
//                //暂定单价
//                gMap.put("purchPrice", purchGoods.getPurchPrice());
                //备注
                gMap.put("remark", purchGoods.getRemark());
                dealGoodsList.add(gMap);
            }
            dataMap.put("dealGoodsList", dealGoodsList);
            //交易标的物  结束

            //获取采购合同补充信息
            //获取合同对应的最新审核信息
            PurchContractApproval purchContractApproval =  purchContractApprovalService.getLatestPurchContractApproval(purch.getId(),1);
            PurchContractReplenishInfo purchContractReplenishInfo = purchContractReplenishInfoService.findByPurchContBasicId(purchContractApproval.getId());
            //工程量类别
            dataMap.put("projectAmountCategory", purchContractReplenishInfo.getProjectAmountCategoryDic().getName());
            //货物单价结算方式
            dataMap.put("goodsPriceSettleMethod", purchContractReplenishInfo.getGoodsPriceSettleMethod());

            //获取增值税要求
//            PurchContractVatInfo purchContractVatInfo = purchContractVatInfoService.findByPurchContApprId(purchContractApproval.getId());
//            //增值税要求 税率
//            dataMap.put("taxRate", purchContractVatInfo.getTaxRate());
//            //增值税要求 发票类型
//            dataMap.put("receiptType", purchContractVatInfo.getReceiptType());
            //开票信息 开票单位名称(需方)
            dataMap.put("openCompanyName", platform.getPlatformName());
            //开票信息 开票单位统一社会信用代码
            dataMap.put("openCompanySocialCreditCode", platform.getSocialCreditCode());
            //开票信息 地址
            dataMap.put("openCompanyAddress", platform.getAddress());
            //开票信息 电话
            dataMap.put("openCompanyPhoneNumber", platform.getPhoneNumber());
            //开票信息 发票开户行
//            dataMap.put("openBank", purchContractVatInfo.getOpenBank()) ;
//            //开票信息 发票账号
//            dataMap.put("receiptAccount", purchContractVatInfo.getReceiptAccount()) ;
//            //发票备注
//            dataMap.put("receiptRemark", purchContractVatInfo.getReceiptRemark()) ;

            //获取采购合同质量与验收
            PurchContractQualityAccept purchContractQualityAccept = purchContractQualityAcceptService
                    .lambdaQuery().eq(PurchContractQualityAccept::getPurchContractApprovalId,purchContractApproval.getId()).one();
            //验收标准
            dataMap.put("acceptCriteria", purchContractQualityAccept.getAcceptCriteria());
            //质量标准
            dataMap.put("qualityCriteria", purchContractQualityAccept.getQualityCriteria());

            //获取采购合同结算与付款
            PurchContractSettlePayment purchContractSettlePayment = purchContractSettlePaymentService.findByPurchContApprId(purchContractApproval.getId());
            //结算方式
            PurchContractApprovalSettlePayment approvalSettlePayment = purchContractApprovalSettlePaymentService.lambdaQuery()
                    .eq(PurchContractApprovalSettlePayment::getPurchContractApprovalId, purchContractApproval.getId())
                    .orderByDesc(PurchContractApprovalSettlePayment::getUserCreate).last("limit 1").one();
            Dictionary settleMethodDic = dictService.getByCode(approvalSettlePayment.getSettleMethod());
            dataMap.put("settleMethod",settleMethodDic.getName());
            //付款方式
            dataMap.put("paymentMethod", approvalSettlePayment.getPaymentMethod());

            //获取采购合同交货规定
            PurchContractDeliverClause purchContractDeliverClause = purchContractDeliverClauseService
                    .lambdaQuery().eq(PurchContractDeliverClause::getPurchContractApprovalId,purchContractApproval.getId()).one();
            //交货方式
            dataMap.put("deliverMethod", purchContractDeliverClause.getDeliverMethod());
            //交货地点
            dataMap.put("deliverSite", purchContractDeliverClause.getDeliverSite());

//            //需方收货人  开始
//            List<Map<String, Object>> receiverList = new ArrayList<>();
//            //获取采购合同需方收货人
//            List<PurchContractBuyerReceiver> buyerReceiverList = purchContractBuyerReceiverService.findByPurchContApprId(purchContractApproval.getId());
//            int i = 1;
//            for (PurchContractBuyerReceiver buyerReceiver : buyerReceiverList) {
//                Map<String, Object> bMap = new HashMap<>();
//                //序号
//                bMap.put("receiverId", i);
//                //姓名
//                bMap.put("receiverName", buyerReceiver.getName());
//                //身份证号
//                bMap.put("receiverCertno", buyerReceiver.getCertno());
//                //联系方式
//                bMap.put("receiverContact", buyerReceiver.getContact());
//                receiverList.add(bMap);
//                i++;
//            }
//            dataMap.put("receiverList", receiverList);
//            //需方收货人  结束
//
//            //供应商发货人  开始
//            List<Map<String, Object>> senderList = new ArrayList<>();
//            //采购合同供货商发货人
//            List<PurchContractSellerSender> sellerSenderList = purchContractSellerSenderService.findByPurchContApprId(purchContractApproval.getId());
//            int j = 1;
//            for (PurchContractSellerSender sellerSender : sellerSenderList) {
//                Map<String, Object> sMap = new HashMap<>();
//                //序号
//                sMap.put("sellerId", j++);
//                //姓名
//                sMap.put("sellerName", sellerSender.getName());
//                //身份证号
//                sMap.put("sellerCertno", sellerSender.getCertno());
//                //联系方式
//                sMap.put("sellerContact", sellerSender.getContact());
//                receiverList.add(sMap);
//            }
//            dataMap.put("senderList", senderList);
//            //供应商发货人  结束

//            //需方指定验收人
//            //姓名
//            dataMap.put("acceptName", buyerReceiverList.get(0).getName());
//            //身份证号
//            dataMap.put("acceptCertno", buyerReceiverList.get(0).getCertno());
//            //联系方式
//            dataMap.put("acceptContact", buyerReceiverList.get(0).getContact());
//            //需方指定结算人
//            //姓名
//            dataMap.put("paymentName", buyerReceiverList.get(0).getName());
//            //身份证号
//            dataMap.put("paymentCertno", buyerReceiverList.get(0).getCertno());
//            //联系方式
//            dataMap.put("paymentContact", buyerReceiverList.get(0).getContact());

            //获取采购合同供货商责任
            PurchContractSellerBlame purchContractSellerBlame = purchContractSellerBlameService.findByPurchContApprId(purchContractApproval.getId());
            //供应商违约金比例
            dataMap.put("penaltyRate", purchContractSellerBlame.getPenaltyRate());
            //向谁出售  买方名称
            dataMap.put("toWhoPurchaserName", purchaserCustomer.getEnterpriseName());

            //获取采购合同违约条款
            PurchContractPunishClause purchContractPunishClause = purchContractPunishClauseService.findByPurchContApprId(purchContractApproval.getId());
            //合同补偿金
            dataMap.put("contractCompensateRate", purchContractPunishClause.getContractCompensateRate());
            //合同违约金比例
            dataMap.put("contractPenaltyRate", purchContractPunishClause.getContractPenaltyRate());

            //获取其他条款
            List<PurchContractOtherClause> contractOtherClauseList = purchContractOtherClauseService.findByPurchContApprId(purchContractApproval.getId());
            //其他条款  开始
            List<Map<String, Object>> otherClauseList = new ArrayList<>();
            for (PurchContractOtherClause otherClause : contractOtherClauseList) {
                Map<String, Object> cMap = new HashMap<>();
                //序号
                cMap.put("serialNumber",   otherClause.getSerialNumber() );
                //付款条件
                cMap.put("paymentCondition", otherClause.getPaymentCondition());
                otherClauseList.add(cMap);
            }
            dataMap.put("otherClauseList", otherClauseList);
            //其他条款  结束

            //单位名称需方公司名称
            dataMap.put("companyPlatformName", platform.getPlatformName());
            //单位名称供应商名称
            dataMap.put("companySupplierName", supplierCustomer.getEnterpriseName());

            //需方签订日期  需处理
            dataMap.put("companyPlatformDate", null);
            //供应商签订日期  需处理
            dataMap.put("companySupplierDate", null);

            File outFile = null;
            outFile = xmlDoc.makePurchContract(dataMap, contractName, "/ftl/purchcontract/export/",
                    "PurchContract.zip");
            list.add(outFile);
        } catch (Exception e) {
            e.printStackTrace();
            throw new BusinessException(CodeUtil.FAIL, "下载采购合同错误" + e.getMessage());
        }
    }

    @Override
    public void exportPurchContract(String businessKey, String taskId, HttpServletRequest request, HttpServletResponse response) {
        PurchContractManagement purchContractManagement = purchContractService.getById(businessKey);

        PurchContractBasicInfo purch = purchContractBasicInfoService.lambdaQuery()
                .eq(PurchContractBasicInfo::getPurchContractManagementId, purchContractManagement.getId()).one();

        List<File> list = createPurchContractDocument(purchContractManagement, purch, taskId, request, response);
        if(purch != null && list != null){
            if(StringUtil.isNotEmpty(purch.getContractName())){
                // 打包成zip文件
                File zipFile = downloadZip(list, purch.getContractName());
                // 下载zip附件
                doUploadFile(response, zipFile);
            }
        }

    }

    /**
     * 下载zip文件
     */
    private File downloadZip(List<File> fileList, String contractName) {

        try {
            contractName = new String(contractName.getBytes("UTF-8"));
        } catch (UnsupportedEncodingException e1) {
            throw new BusinessException(CodeUtil.FAIL, "下载合同附件转码失败：" + e1.getMessage());
        }
        String desPath = FileUtil.getAbsolutePath(contractName, ".zip", PURCHASE_CONTRACT_FILE);
        File zipFile = new File(desPath);
        if (!zipFile.getParentFile().exists()) {
            zipFile.getParentFile().mkdirs();
        }
        ZipOutputStream zipStream = null;
        FileInputStream zipSource = null;
        BufferedInputStream bufferStream = null;
        try {
            // 构造最终压缩包的输出流
            zipStream = new ZipOutputStream(new FileOutputStream(zipFile));
            for (File file : fileList) {
                // 将需要压缩的文件格式化为输入流
                zipSource = new FileInputStream(file);
                // 压缩条目不是具体独立的文件，而是压缩包文件列表中的列表项，称为条目，就像索引一样
                ZipEntry zipEntry = new ZipEntry(file.getName());
                // 定位该压缩条目位置，开始写入文件到压缩包中
                zipStream.putNextEntry(zipEntry);
                // 输入缓冲流
                bufferStream = new BufferedInputStream(zipSource, 1024 * 10);
                int read = 0;
                // 创建读写缓冲区
                byte[] buf = new byte[1024 * 10];
                while ((read = bufferStream.read(buf, 0, 1024 * 10)) != -1) {
                    zipStream.write(buf, 0, read);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 关闭流
            try {
                if (null != bufferStream)
                    bufferStream.close();
                if (null != zipStream)
                    zipStream.close();
                if (null != zipSource)
                    zipSource.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return zipFile;
    }

    private void doUploadFile(HttpServletResponse res, File file) {
        try {
            if (file.exists()) {
                String fileName = file.getName();
                fileName = new String(fileName.getBytes("UTF-8"));
                String basePath = file.getAbsolutePath();
                InputStream in = new FileInputStream(new File(basePath));
                fileName = URLEncoder.encode(fileName, "UTF-8");
                res.setHeader("content-disposition", "attachment;fileName=" + fileName);
                OutputStream out = res.getOutputStream();
                byte[] b = new byte[1024];
                int len = -1;
                while ((len = in.read(b)) != -1) {
                    out.write(b, 0, len);
                }
                // 关闭
                out.close();
                in.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
