You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用MapReduce脚本创建多CSV文件规避10MB文件大小限制?

解决方案

核心思路

由于无法提前获取未保存文件的实际大小,我们通过逐行累加内容并估算字节长度的方式,当累计大小接近10MB阈值时,立即保存当前文件并新建文件继续存储(每个文件保留表头),避免触发SSS_FILE_CONTENT_SIZE_EXCEEDED错误。同时优化CSV格式生成逻辑,避免特殊字符导致的格式错乱。

修改后的完整代码

function summarize(summary) {
    const datasetObj = dataset.load({"id": 'custdataset70'}); 
    const headers = datasetObj.columns.map(col => col.label || col.id);
    // 转义表头字段,确保CSV格式合法
    const escapedHeaders = headers.map(escapeCSVField).join(',');
    const headerWithNewline = `${escapedHeaders}\n`;
    const headerByteLength = getByteLength(headerWithNewline);

    const MAX_FILE_SIZE = 9.5 * 1024 * 1024; // 设为9.5MB留余量,避免超10MB限制
    let currentContent = [escapedHeaders];
    let currentByteLength = headerByteLength;
    let fileIndex = 1;
    const savedFileIds = [];

    // 逐行遍历数据,实时监控大小
    summary.output.iterator().each((key, value) => {
        // 转义行字段,生成合法CSV行
        const escapedRow = value.map(escapeCSVField).join(',');
        const rowWithNewline = `${escapedRow}\n`;
        const rowByteLength = getByteLength(rowWithNewline);

        // 若添加当前行后超出阈值,保存当前文件并重置内容
        if (currentByteLength + rowByteLength > MAX_FILE_SIZE) {
            const fileId = saveCSVFile(currentContent.join('\n'), fileIndex);
            if (fileId) savedFileIds.push(fileId);
            
            // 重置内容,保留表头
            currentContent = [escapedHeaders];
            currentByteLength = headerByteLength;
            fileIndex++;
        }

        // 将当前行加入内容
        currentContent.push(escapedRow);
        currentByteLength += rowByteLength;
        return true;
    });

    // 保存最后一批剩余内容
    if (currentContent.length > 1) { // 确保不止表头,有实际数据
        const fileId = saveCSVFile(currentContent.join('\n'), fileIndex);
        if (fileId) savedFileIds.push(fileId);
    } else {
        log.debug('No Data', 'No unique dataset records found.');
        return;
    }

    // 批量发送邮件(需调整sendEmail支持多文件ID)
    if (savedFileIds.length > 0) {
        sendEmail(savedFileIds);
    }
}

function saveCSVFile(csvContent, fileIndex) {
    const today = format.format({"value": new Date(), "type": format.Type.DATE});
    // 文件名添加序号,避免同日期文件重名覆盖
    const fileName = `DatasetResults_${today}_${fileIndex}.csv`;
    const csvFile = file.create({
        "name": fileName,
        "fileType": file.Type.CSV,
        "contents": csvContent,
        "folder": 5081389 
    });
    return csvFile.save();
}

// 辅助函数:转义CSV字段,处理逗号、引号、换行符
function escapeCSVField(field) {
    if (typeof field !== 'string') field = String(field);
    if (field.includes(',') || field.includes('"') || field.includes('\n') || field.includes('\r')) {
        return `"${field.replace(/"/g, '""')}"`;
    }
    return field;
}

// 辅助函数:计算字符串UTF-8编码的字节长度
function getByteLength(str) {
    return new TextEncoder().encode(str).length;
}

关键改动说明

  • 字节长度估算:用TextEncoder计算实际字节数,避免按字符数估算的误差(如中文占3字节)。
  • 阈值预留空间:设置9.5MB作为拆分触发点,给文件元数据留足空间,确保最终文件不超10MB限制。
  • CSV格式修复:新增escapeCSVField函数处理特殊字符,防止字段含逗号、引号时导致列错位。
  • 多文件命名:文件名添加序号后缀,避免同一日期下的文件重名覆盖。
  • 实时拆分逻辑:遍历数据时实时监控大小,达到阈值立即保存并重置内容,避免一次性生成超大内容。

注意事项

  • 若平台不支持TextEncoder,可改用encodeURIComponent(str).split(/%..|./).length - 1估算字节数(精度稍低)。
  • 需根据实际情况调整sendEmail函数,使其支持接收多个文件ID数组,实现批量发送。

内容的提问来源于stack exchange,提问作者Maira S

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 04:50:10