关于导出文件的两种思考方式

本文介绍两种导出Excel的方法:一是适用于数据量较小的情况,直接通过流的方式在客户端完成;二是针对大规模数据导出,先在服务器生成文件再供客户端下载。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

有时候我们需要做文件导出的需求,这里以导出excel文件为例,给出两种方式。

1、文件内数据不是很多的时候,比如只有“千”这个数量级的时候,我们可以用“流”的方式从客户端导出,如下代码示例:

/**
     * 入账记录导出为excel表
     * @param response
     * @param qo
     * @return
     * @throws IOException
     */
    @PostMapping("/records/income/export")
    public HttpServletResponse exportIncomeRecord(HttpServletResponse response, @RequestBody IncomeExportQO qo) throws IOException {
        log.info("入账导出excel入参,开始时间戳={},结束时间戳={}", qo.getStartTime(), qo.getEndTime());
        String userId = (String) SecurityUtils.getSubject().getSession().getAttribute("id");
        Date startDate = null;
        Date endDate = null;
        if (!StringUtils.isBlank(qo.getStartTime())) {
            startDate = DateUtils.tranTimestampForDate(qo.getStartTime());
        }
        if (!StringUtils.isBlank(qo.getEndTime())) {
            endDate = DateUtils.tranTimestampForDate(qo.getEndTime());
        }
        IncomeExport ie = new IncomeExport();
        ie.setStartDate(startDate);
        ie.setEndDate(endDate);
        ie.setUserId(userId);
        log.info("入账导出excel,开始时间={},结束时间={}", startDate, endDate);
        List<IncomeExportVo> voList = recordService.incomeExport(ie);
        log.info("提现查询出来的数据条数:" + voList.size());
        //以上为业务代码,仅仅是为了获取数据集合voList
        ExcelWriter writer = ExcelUtil.getWriter();
        //设置excel单元格大小
        writer.setColumnWidth(0, 40);
        writer.setColumnWidth(1, 35);
        writer.setColumnWidth(2, 30);
        writer.setColumnWidth(3, 20);
        writer.setColumnWidth(4, 10);
        writer.setColumnWidth(5, 20);
        //writer.setColumnWidth(6, 20);
        writer.setColumnWidth(6, 30);
        //设置excel单元格标题
        writer.merge(6, "入账记录表");
        //填充excel单元格数据
        if(voList != null && voList.size() > 0){
            writer.addHeaderAlias("incomeId", "入账流水号");
            writer.addHeaderAlias("foreignBankAccount", "收款银行账号");
            writer.addHeaderAlias("platform", "平台");
            writer.addHeaderAlias("money", "入账金额");
            writer.addHeaderAlias("currency", "币种");
            writer.addHeaderAlias("leftMoney", "可用余额");
            //writer.addHeaderAlias("status", "状态");
            writer.addHeaderAlias("gmtCreate", "创建日期");
            writer.write(voList, true);
        }else{
            writer.writeCellValue(0, 1, "入账流水号");
            writer.writeCellValue(1, 1, "收款银行账号");
            writer.writeCellValue(2, 1, "平台");
            writer.writeCellValue(3, 1, "入账金额");
            writer.writeCellValue(4, 1, "币种");
            writer.writeCellValue(5, 1, "可用余额");
            writer.writeCellValue(6, 1, "创建日期");
        }
        //设置字体及标题栏高度
        Font font = writer.createFont();
        font.setFontHeight((short) 250);
        writer.getStyleSet().setFont(font, true);
        writer.setRowHeight(0, 20);
        writer.setRowHeight(1, 20);
        response.setContentType("application/vnd.ms-excel;charset=utf-8");
        response.setHeader("Content-Disposition","attachment;filename=incomeRecord.xls");
        ServletOutputStream out = response.getOutputStream();
        writer.flush(out, true);
        writer.close();
        IoUtil.close(out);
        return response;
    }

2、当需要的导出以“万”为数量级的时候,用流的方式显得无力了,即客户端下载的会非常非常慢,所以此时换一种方式,现将文件生成,放到服务器上,让客户端从服务器上下载,就会非常快,如下业务代码:

        //生成服务器路劲
        String newFileName = System.nanoTime() + ".xlsx";
        String fileDir = "/" + new SimpleDateFormat("yyyyMMdd").format(new Date());
        //uploadFileProperties.getSaveDir()为服务器中某个文件夹路径,我这里是/data/images/news/admin
        File dir = new File(uploadFileProperties.getSaveDir() + fileDir);
//        File dir = new File("/Users/chenjianwen/myDisk" + fileDir);
        if (!dir.exists()) {
            dir.mkdirs();
        }
        String filePath = fileDir + "/" + newFileName;
        BigExcelWriter writer= ExcelUtil.getBigWriter(new File(uploadFileProperties.getSaveDir() + fileDir + "/" + newFileName));
//        BigExcelWriter writer = ExcelUtil.getBigWriter(new File("/Users/chenjianwen/myDisk" + fileDir + "/" + newFileName));
        //设置excel单元格大小
        writer.setColumnWidth(0, 30);
        writer.setColumnWidth(1, 30);
        writer.setColumnWidth(2, 30);
        writer.setColumnWidth(3, 30);
        writer.setColumnWidth(4, 20);
        writer.setColumnWidth(5, 20);
        writer.setColumnWidth(6, 30);
        writer.setColumnWidth(7, 20);
        writer.setColumnWidth(8, 20);
        writer.setColumnWidth(9, 30);
        writer.setColumnWidth(10, 20);
        writer.setColumnWidth(11, 20);
        writer.setColumnWidth(12, 10);
        //设置excel单元格标题
        writer.merge(12, "流水记录");
        //填充excel单元格数据
        if(incomeRecordAdminVoList != null && incomeRecordAdminVoList.size() > 0){
            writer.addHeaderAlias("id", "流水号");
            writer.addHeaderAlias("bankAccount", "银行卡号");
            writer.addHeaderAlias("fid", "国外银行账号id");
            writer.addHeaderAlias("userId", "用户ID");
            writer.addHeaderAlias("money", "金额");
            writer.addHeaderAlias("ableMoney", "可用金额");
            writer.addHeaderAlias("currency", "币种");
            writer.addHeaderAlias("payAccount", "付款人信息");
            writer.addHeaderAlias("uploadTime", "审核创建时间");
            writer.addHeaderAlias("createTime", "创建时间");
            writer.addHeaderAlias("remarks", "备注");
            writer.addHeaderAlias("auditFailReason", "审核失败原因");
            writer.addHeaderAlias("status", "状态(0签名审核通过,用户可提现 1未到账(amazon) 2对账不平(amazon)  3需提交订单  4审核的订单有误 5等待订单审核  6等待发票生成  7发票生成完毕,等待用户签名 8等待后台审核签名 9用户已申请提现 10已拆分 11冻结中 12可用余额已结完 13已汇总)");
            writer.write(incomeRecordAdminVoList, true);
        }else{
            writer.writeCellValue(0, 1, "流水号");
            writer.writeCellValue(1, 1, "银行卡号");
            writer.writeCellValue(2, 1, "国外银行账号id");
            writer.writeCellValue(3, 1, "用户ID");
            writer.writeCellValue(4, 1, "金额");
            writer.writeCellValue(5, 1, "可用金额");
            writer.writeCellValue(6, 1, "币种");
            writer.writeCellValue(7, 1, "付款人信息");
            writer.writeCellValue(8, 1, "审核创建时间");
            writer.writeCellValue(9, 1, "创建时间");
            writer.writeCellValue(10, 1, "备注");
            writer.writeCellValue(11, 1, "审核失败原因");
            writer.writeCellValue(12, 1, "状态");
        }
        //设置字体
        Font font = writer.createFont();
        font.setFontHeight((short) 240);
        writer.getStyleSet().setFont(font, true);
        writer.close();
        //uploadFileProperties.getImageServerDomain()是服务器域名
        return MessageVo.newBuilder().code(200).data(uploadFileProperties.getImageServerDomain() + "/news/admin" + filePath).build();
//        return MessageVo.newBuilder().code(200).data("/Users/chenjianwen/myDisk" + filePath).build();

<think>好的,我现在需要解决用户的问题,关于如何在Substance Painter中导出适用于Unity的.sbsar文件。首先,我要确认用户的需求是什么。用户提到他们想找到导出.sbsar文件的方法或教程,所以需要了解Substance Painter和Unity之间的文件交互流程。 首先,我回忆一下Substance Painter的主要输出格式。通常,Substance Painter导出的是纹理贴图,比如Albedo、Normal、Metallic等,这些是常见的图像文件,如PNG或TGA。但用户询问的是.sbsar文件,这是Substance的自定义格式,通常用于Substance Designer或Substance Player中的材质编辑,可能用户希望保留材质的可调整性,而不仅仅是静态贴图。 接下来,我需要确认Substance Painter是否支持直接导出.sbsar文件。根据我之前的知识,Substance Painter主要用于纹理绘制,而.sbsar文件通常是由Substance Designer生成的材质文件。Substance Painter的项目文件.spp,而.sbsar是Substance的存档格式,包含材质的不同参数和通道,允许在支持的引擎中实时调整。因此,可能用户混淆了这两个软件的功能。 不过,可能存在一种方法将Substance Painter中的材质转换为.sbsar。可能需要结合Substance Designer或其他工具。例如,用户可能在Substance Designer中创建基础材质,然后在Painter中进行细节绘制,再导出.sbsar。但需要验证这一点。 查看用户提供的引用内容,其中引用[2]提到Substance Painter导出贴图时需要注意颜色空间设置,引用[3]提到使用Substance Painter和Blender创建角色并导入Unity,但未提到.sbsar的导出。引用[4]讨论了Metallic和Smoothness的调整,属于贴图应用部分。因此,现有的引用中没有直接关于导出.sbsar的信息,需要基于外部知识回答。 进一步思考,Substance Painter本身可能不支持直接导出.sbsar文件.sbsar通常由Substance Designer生成,而Painter用于纹理绘制。用户可能希望将Painter中的材质导出为可在Unity中实时调整的.sbsar格式,但需要确认是否有这样的流程。或者,用户可能希望使用Substance插件在Unity中直接使用.sbsar文件,这时可能需要将材质导出.sbsar并在Unity中通过Substance插件加载。 可能的解决步骤:首先在Substance Designer中创建材质,导出.sbsar,然后在Substance Painter中使用该材质进行纹理绘制,最后在Unity中通过Substance插件导入.sbsar。但Painter本身是否支持导出.sbsar?根据我的了解,Painter主要处理纹理绘制,生成的是贴图而非材质球文件。因此,正确的流程可能是在Designer中制作材质,导出.sbsar,然后在Unity中使用Substance插件进行参数调整。而Painter的导出是针对贴图的,不是.sbsar。 因此,用户可能需要的是在Substance Designer中创建材质并导出.sbsar,而不是在Painter中。如果用户确实需要在Painter中处理,可能需要结合其他工具,或者用户误解了文件格式的用途。此时,正确的回答应指出Substance Painter无法直接导出.sbsar,并建议使用Designer生成.sbsar,然后在Unity中使用Substance插件进行导入和调整。 此外,需要检查是否有第三方工具或工作流可以将Painter项目转换为.sbsar。可能存在导出材质到Designer再生成.sbsar的步骤,但需要具体步骤说明。或者,用户可能需要使用Substance Integration插件在Unity中处理.sbsar文件,这需要安装相应的插件。 总结回答的结构:首先澄清.sbsar文件通常由Substance Designer生成,Painter主要用于导出贴图。如果用户需要.sbsar,应使用Designer,并说明如何在Unity中使用这些文件。同时,如果用户确实需要在Painter中处理,可能需要导出贴图并在Unity中手动设置材质参数,引用相关的颜色空间设置(如引用[2]中的sRGB选项)。</think>### 如何在Substance Painter中导出Unity兼容的.sbsar文件? **关键说明**: Substance Painter **不支持直接导出.sbsar文件**。`.sbsar`文件是Substance Designer生成的材质资源文件,包含可调节参数和程序化材质逻辑[^3]。Substance Painter的核心功能是纹理绘制,其输出为静态贴图(如Albedo、Normal等),而非可编程的材质文件。若需使用`.sbsar`文件,需通过以下两种方式实现: --- ### 方案一:**通过Substance Designer生成.sbsar** 1. **在Substance Designer中创建材质** - 使用Substance Designer设计程序化材质,定义参数(如颜色、粗糙度等)。 - 导出为`.sbsar`文件,该文件支持在Unity中通过**Substance插件**动态调整参数。 2. **在Unity中使用.sbsar** - 安装Unity的**Substance3D插件**(需从Adobe获取或通过Package Manager导入)。 - 将`.sbsar`文件拖入Unity项目,右键选择**“Reimport with Substance”**,即可在Inspector面板中调整参数。 --- ### 方案二:**Substance Painter导出贴图 + Unity手动配置** 若仅需静态贴图,Substance Painter的标准流程如下: 1. **导出贴图** - 完成纹理绘制后,通过`File > Export Textures`选择**Unity模板**(如“Unity 5 (Standard Metallic)”)。 - 确保勾选以下通道: - **Base Color (Albedo)**:勾选`sRGB`(若Unity使用线性空间)[^2]。 - **Normal**:无需sRGB。 - **Metallic/Smoothness**:合并导出,根据引用[4]调整参数。 2. **Unity材质设置** - 创建`Standard Shader`材质,将贴图分别拖入对应插槽。 - 调整`Metallic`和`Smoothness`值以控制反光强度[^4]。 --- ### 常见问题解答 **Q1: 能否将Substance Painter项目转换为.sbsar?** 目前无直接转换工具。需在Substance Designer中重建材质逻辑,或通过Substance Painter导出贴图后,在Unity中手动配置材质。 **Q2: Unity中如何动态调整.sbsar材质参数?** 需通过脚本调用Substance API,例如: ```csharp SubstanceGraphSO substance = GetComponent<SubstanceGraphSO>(); substance.SetInputFloat("Metallic", 0.5f); substance.QueueForRender(); substance.ApplyAndUpdateMaterials(); ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值