如何在SAS存储过程(Stored Process)中生成多个CSV导出文件
问题根因
HTTP协议单请求仅支持返回1个附件,响应头会在内容输出前就发送到浏览器,你原有代码在同一个请求中多次修改Content-Disposition头、在同一个输出流拼接两份CSV内容的写法无效,浏览器只会识别首次返回的第一个CSV文件。
调整方案
提供两种可落地的实现方式:
方案1:点击按钮触发两次独立下载请求(无压缩包,直接得到两个CSV)
步骤1:调整前端HTML代码
替换原有表单逻辑,新增JS点击事件,一次点击触发两次下载请求:
data _null_; format infile $char256.; input; infile = resolve(_infile_); file _webout; put infile; cards4; <style> input[type='submit'] { border-radius: 10px; cursor: pointer; padding: 8px 20px; font-size: 14px; } </style> <HTML> <BODY> <H2 align="center">Deseja atualizar a Base?</H2> <H3 align="center">(Tempo estimado: 15 minutos)</H3> <div align="center"> <input type="submit" value="Atualizar" id="downloadBtn"> </div> <script> document.getElementById('downloadBtn').addEventListener('click', function() { // 触发第一个CSV下载,对应后端FILE1导出接口 window.open('http://mydir?_program=/export_file1', '_blank'); // 延迟200ms触发第二个CSV下载,避免浏览器拦截 setTimeout(() => { window.open('http://mydir?_program=/export_file2', '_blank'); }, 200); }); </script> </BODY> </HTML> ;;;; run;
步骤2:拆分后端SAS核心代码为两个独立存储过程
存储过程1:/export_file1 仅导出FILE1
%let hoje = %sysfunc(today(),date9.); %let rc=%sysfunc(stpsrv_header(Content-type,text/csv)); %let rc=%sysfunc(stpsrv_header(Content-disposition,attachment%str(;) filename=FILE1_&HOJE..csv)); %let _ODSSTYLE=PEARL; ods csv file=_webout options(autofit_height='YES' FROZEN_HEADERS='YES' delimiter="|"); PROC PRINT DATA=FILE1 noobs LABEL style(HEADER)={color=black background=white font_weight=bold font_size=10pt font_face=CALIBRI width=1.8in just=c vjust=c} style(DATA) = {background=white font_size=10pt font_face=CALIBRI}; format MYVAR $char.; RUN; ods csv close;
存储过程2:/export_file2 仅导出FILE2
%let hoje = %sysfunc(today(),date9.); %let rc=%sysfunc(stpsrv_header(Content-type,text/csv)); %let rc=%sysfunc(stpsrv_header(Content-disposition,attachment%str(;) filename=FILE2_&HOJE..csv)); %let _ODSSTYLE=PEARL; ods csv file=_webout options(autofit_height='YES' FROZEN_HEADERS='YES' delimiter="|"); PROC PRINT DATA=FILE2 noobs LABEL style(HEADER)={color=black background=white font_weight=bold font_size=10pt font_face=CALIBRI width=1.8in just=c vjust=c} style(DATA) = {background=white font_size=10pt font_face=CALIBRI}; RUN; ods csv close;
方案2:单请求返回压缩包(仅一次下载,解压得到两个CSV)
无需修改前端,仅调整后端SAS代码,将两个CSV打包为ZIP返回:
%let hoje = %sysfunc(today(),date9.); /* 先创建临时ZIP文件 */ filename outzip ZIP "%sysfunc(getoption(WORK))/output.zip" member='FILE1_&HOJE..csv'; /* 写入第一个CSV到ZIP */ ods csv file=outzip options(autofit_height='YES' FROZEN_HEADERS='YES' delimiter="|"); PROC PRINT DATA=FILE1 noobs LABEL style(HEADER)={color=black background=white font_weight=bold font_size=10pt font_face=CALIBRI width=1.8in just=c vjust=c} style(DATA) = {background=white font_size=10pt font_face=CALIBRI}; format MYVAR $char.; RUN; ods csv close; /* 切换ZIP成员,写入第二个CSV */ filename outzip ZIP "%sysfunc(getoption(WORK))/output.zip" member='FILE2_&HOJE..csv'; ods csv file=outzip options(autofit_height='YES' FROZEN_HEADERS='YES' delimiter="|"); PROC PRINT DATA=FILE2 noobs LABEL style(HEADER)={color=black background=white font_weight=bold font_size=10pt font_face=CALIBRI width=1.8in just=c vjust=c} style(DATA) = {background=white font_size=10pt font_face=CALIBRI}; RUN; ods csv close; /* 返回ZIP文件给前端 */ %let rc=%sysfunc(stpsrv_header(Content-type,application/zip)); %let rc=%sysfunc(stpsrv_header(Content-disposition,attachment%str(;) filename=EXPORT_&HOJE..zip)); /* 输出ZIP到_webout */ data _null_; infile "%sysfunc(getoption(WORK))/output.zip" recfm=n; file _webout recfm=n; input byte $char1. @; put byte $char1. @; run; filename outzip clear;
内容的提问来源于stack exchange,提问作者JOAO RF
相关产品推荐
相关产品推荐

