这是this question的后续问题。
我正在尝试简化将图片嵌入HTML结果的方式。这个想法的灵感来自this other question。
基本上我要做的是编写一个函数式宏(称为%html_embed_image()
)来获取图像,并将其转换为适合在HTML <img src="">
块中使用的base64格式
给出如下图像:
用法是:
data _null_;
file _webout;
put "<img src=""%html_embed_image(iFileName=hi.png)"" />";
run;
最终输出将是:
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAIAAAAC64paAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAABaSURBVDhP5YxbCsAgDAS9/6XTvJTWNUSIX3ZAYXcdGxW4QW6Khw42Axne81LG0shlRvVVLyeTI2aZ2fcPyXwPdBI8B999NK/gKTaGyxaMX8gTJRkpyREFmegBTt8lFJjOey0AAAAASUVORK5CYII=" />
question linked above 显示了如何在常规datastep代码中执行此操作,但我在使用函数样式宏时遇到问题。我posted a simplified problem我之前遇到过,Tom能够解决这个简化的问题,但它似乎并没有在函数式宏的更大的上下文中工作。
到目前为止,这是我的代码(导致问题的行包含两个put语句,表明它是问题):
option mprint symbolgen;
%macro html_embed_image(iFileName=);
%local rc fid rc2 str str_length format_length format_mod base64_format base64_string;
/* ONLY READ IN 16K CHUNKS AS CONVERTING TO BASE64 */
/* INCREASES SIZE AND DONT WANT TO EXCEED 32K. */
%let rc = %sysfunc(filename(filrf, &iFileName, , lrecl=16000));
%let fid = %sysfunc(fopen(&filrf, i, 16000, b));
%if &fid > 0 %then %do;
%let rc = %sysfunc(fread(&fid));
%do %while(&rc eq 0);
%let rc2 = %sysfunc(fget(&fid,str,16000));
%let str = %superq(str);
/* FORMAT LENGTH NEEDS TO BE 4n/3 ROUNDED UP TO NEAREST MULTIPLE OF 4 */
%let str_length = %length(&str);
%let format_length = %sysevalf(4*(&str_length/3));
%let format_mod = %sysfunc(mod(&format_length,4));
%if &format_mod ne 0 %then %do;
%let format_length = %sysevalf(&format_length - &format_mod + 4);
%end;
%let base64_format = %sysfunc(cats($base64x,&format_length,.));
%put &=base64_format;
/* CONVERT THE BINARY DATA TO BASE64 USING THE CALCULATED FORMAT */
%put PROBLEM START;
%let base64_string = %sysfunc(putc(&str,&base64_format));
%put PROBLEM END;
%put &=base64_string;
/*&base64_string*/ /* RETURN RESULT HERE - COMMENTED OUT UNTIL WORKING */
%let rc = %sysfunc(fread(&fid));
%end;
%end;
%else %do;
%put %sysfunc(sysmsg());
%end;
%let rc=%sysfunc(fclose(&fid));
%let rc=%sysfunc(filename(filrf));
%mend;
测试代码:
%put %html_embed_image(iFileName=hi.png);
结果:
ERROR: Expected close parenthesis after macro function invocation not found.
有关如何解决此问题的任何提示或建议的解决方法都会很棒。
答案 0 :(得分:0)
只需使用数据步骤编写文本。
public String saveImage(MultipartFile file, String imageName) {
try {
String bucketName = "bucket";
AmazonS3 s3client = new AmazonS3Client(
new BasicAWSCredentials("*****", "******"));
TransferManager transferManager = new TransferManager(s3client);
// Otherwise: (Service: Amazon S3; Status Code: 301; Error Code:
// PermanentRedirect)
// s3client.setRegion(Region.getRegion(Regions.EU_WEST_1));
ObjectMetadata objectMetadata = new ObjectMetadata();
objectMetadata.setContentDisposition("attachment; filename=" + file.getOriginalFilename());
Upload upload = transferManager.upload(bucketName, imageName, file.getInputStream(), objectMetadata);
upload.waitForUploadResult();
return "https://path-region/" + bucketName + "/" + imageName;
} catch (Exception e) {
return "You failed to upload " + e.getMessage();
}
}
10:31:00,313 WARN [com.amazonaws.services.s3.AmazonS3Client] (s3-transfer-manag
er-worker-1) No content length specified for stream data. Stream contents will
be buffered in memory and could result in out of memory errors.
如果你真的想在线生成文本,最好添加引号,这样你就可以在PUT语句的中间调用宏而不用担心达到最大字符串长度。
%let fname=hi.png;
data _null_;
file _webout recfm=n;
if _n_=1 then put '<img src="data:image/png;base64,';
length str $60 coded $80 ;
infile "&fname" recfm=n eof=eof;
do len=1 to 60;
input ch $char1.;
substr(str,len,1)=ch;
end;
put str $base64x80.;
return;
eof:
len=len-1;
clen=4*ceil(len/3);
coded = putc(substr(str,1,len),cats('$base64x',clen,'.'));
put coded $varying80. clen ;
put '" />';
run;
那么你的示例数据步骤就像这样:
%macro base64(file);
%local filerc fileref rc fid text len ;
%*----------------------------------------------------------------------
Assign fileref and open the file.
-----------------------------------------------------------------------;
%let fileref = _fread;
%let filerc = %sysfunc(filename(fileref,&file));
%let fid = %sysfunc(fopen(&fileref,s,60,b));
%*----------------------------------------------------------------------
Read file and dump as quoted BASE64 text.
-----------------------------------------------------------------------;
%if (&fid > 0) %then %do;
%do %while(%sysfunc(fread(&fid)) = 0);
%do %while(not %sysfunc(fget(&fid,text,60)));
%let len = %eval(4*%sysfunc(ceil(%length(%superq(text))/3)));
%if (&len) %then "%sysfunc(putc(%superq(text),$base64x&len..))" ;
%end;
%end;
%let rc = %sysfunc(fclose(&fid));
%end;
%*----------------------------------------------------------------------
Clear fileref assigned by macro,
-----------------------------------------------------------------------;
%if ^(&filerc) %then %let rc = %sysfunc(filename(fileref));
%mend base64;