Macros for SAS Application Developers
https://github.com/sasjs/core
Loading...
Searching...
No Matches
mv_createfile.sas
Go to the documentation of this file.
1/**
2 @file
3 @brief Creates a file in SAS Drive using the API method
4 @details Creates a file in SAS Drive using the API interface.
5 If the parent folder does not exist, it is created.
6 The API approach is more flexible than using the filesrvc engine of the
7 filename statement, as it provides more options.
8
9 SAS docs: https://developer.sas.com/rest-apis/files/createNewFile
10
11 Usage:
12
13 filename myfile temp;
14 data _null_;
15 file myfile;
16 put 'something';
17 run;
18 %mv_createfile(path=/Public/temp,name=newfile.txt,inref=myfile)
19
20 The macro also supports find & replace (used by the SASjs Streaming App
21 build program). This allows one string to be replaced by another at the
22 point at which the file is created. This is done by passing in the NAMES of
23 the macro variables containing the values to be swapped, eg:
24
25 filename fref temp;
26 data _null_;
27 file fref;
28 put 'whenever life gets you down, Mrs Brown..';
29 run;
30 %let f=Mrs Brown;
31 %let r=just remember that you're standing on a planet that's evolving;
32 %mv_createfile(path=/Public,name=life.md,inref=fref,fin,swap=f r)
33
34
35 @param [in] path= The parent (SAS Drive) folder in which to create the file
36 @param [in] name= The name of the file to be created
37 @param [in] inref= The fileref pointing to the file to be uploaded
38 @param [in] intype= (BINARY) The type of the input data. Valid values:
39 @li BINARY File is copied byte for byte using the mp_binarycopy.sas macro.
40 @li BASE64 File will be first decoded using the mp_base64.sas macro, then
41 loaded byte by byte to SAS Drive.
42 @param [in] contentdisp= (attchment) Content Disposition. Example values:
43 @li inline
44 @li attachment
45 @param [in] ctype= (0) The actual MIME type of the file (if blank will be
46 determined based on file extension))
47 @param [in] access_token_var= The global macro variable to contain the access
48 token, if using authorization_code grant type.
49 @param [in] grant_type= (sas_services) Valid values are:
50 @li password
51 @li authorization_code
52 @li sas_services
53 @param [in] force= (YES) Will overwrite (delete / recreate) files by default.
54 Set to NO to abort if a file already exists in that location.
55 @param pin] swap= (0) Provide two macro variable NAMES that contain the values
56 to be swapped, eg swap=find replace (see also the example above)
57 @param [out] outds= (_null_) Output dataset with the uri of the new file
58
59 @param [in] mdebug= (0) Set to 1 to enable DEBUG messages
60
61 <h4> SAS Macros </h4>
62 @li mf_getplatform.sas
63 @li mf_getuniquefileref.sas
64 @li mf_getuniquename.sas
65 @li mf_isblank.sas
66 @li mf_mimetype.sas
67 @li mfv_getpathuri.sas
68 @li mp_abort.sas
69 @li mp_base64copy.sas
70 @li mp_replace.sas
71 @li mv_createfolder.sas
72 @li mv_getviyafileextparms.sas
73
74 <h4> Related Macros</h4>
75 @li mv_createfile.sas
76
77**/
78
79%macro mv_createfile(path=
80 ,name=
81 ,inref=
82 ,intype=BINARY
83 ,contentdisp=attachment
84 ,ctype=0
85 ,access_token_var=ACCESS_TOKEN
86 ,grant_type=sas_services
87 ,mdebug=0
88 ,outds=_null_
89 ,force=YES
90 ,swap=0
91 );
92%local dbg;
93%if &mdebug=1 %then %do;
94 %put &sysmacroname entry vars:;
95 %put _local_;
96%end;
97%else %let dbg=*;
98
99%mp_abort(
100 iftrue=(&syscc ne 0),
101 msg=Cannot enter &sysmacroname with syscc=&syscc
102)
103
104%local oauth_bearer;
105%if &grant_type=detect %then %do;
106 %if %symexist(&access_token_var) %then %let grant_type=authorization_code;
107 %else %let grant_type=sas_services;
108%end;
109%if &grant_type=sas_services %then %do;
110 %let oauth_bearer=oauth_bearer=sas_services;
111 %let &access_token_var=;
112%end;
113
114%mp_abort(iftrue=(&grant_type ne authorization_code and &grant_type ne password
115 and &grant_type ne sas_services
116 )
117 ,mac=MV_CREATEFILE
118 ,msg=%str(Invalid value for grant_type: &grant_type)
119)
120
121%mp_abort(iftrue=(%mf_isblank(&path)=1 or %length(&path)=1)
122 ,mac=MV_CREATEFILE
123 ,msg=%str(path value must be provided)
124)
125%mp_abort(iftrue=(%mf_isblank(&name)=1 or %length(&name)=1)
126 ,mac=MV_CREATEFILE
127 ,msg=%str(name value with length >1 must be provided)
128)
129
130/* prep the source file */
131%local fref;
132%let fref=%mf_getuniquefileref();
133
134%if %upcase(&intype)=BINARY %then %let fref=&inref;
135%else %if %upcase(&intype)=BASE64 %then %do;
136 %mp_base64copy(inref=&inref, outref=&fref, action=DECODE)
137%end;
138%else %put %str(ERR)OR: invalid value for intype: &intype;
139
140%if "&swap" ne "0" %then %do;
141 %mp_replace("%sysfunc(pathname(&fref))"
142 ,findvar=%scan(&swap,1,%str( ))
143 ,replacevar=%scan(&swap,2,%str( ))
144 )
145%end;
146
147%if &mdebug=1 %then %do;
148 data _null_;
149 infile &fref lrecl=32767;
150 input;
151 put _infile_;
152 run;
153%end;
154
155options noquotelenmax;
156%local base_uri; /* location of rest apis */
157%let base_uri=%trim(%mf_getplatform(VIYARESTAPI));
158
159/* create folder if it does not already exist */
160%local folderds self_uri;
161%let folderds=%mf_getuniquename(prefix=folderds);
162%mv_createfolder(path=&path
163 ,access_token_var=&access_token_var
164 ,grant_type=&grant_type
165 ,mdebug=&mdebug
166 ,outds=&folderds
167)
168data _null_;
169 set &folderds;
170 call symputx('self_uri',self_uri,'l');
171run;
172
173/* abort or delete if file already exists */
174%let force=%upcase(&force);
175%local fileuri ;
176%let fileuri=%trim(%mfv_getpathuri(&path/&name));
177%mp_abort(iftrue=(%mf_isblank(&fileuri)=0 and &force ne YES)
178 ,mac=MV_CREATEFILE
179 ,msg=%str(File &path/&name already exists and force=&force)
180)
181%mp_abort(
182 iftrue=(&syscc ne 0),
183 mac=MV_CREATEFILE182
184 msg=syscc=&syscc after mfv_getpathuri
185)
186
187%if %mf_isblank(&fileuri)=0 and &force=YES %then %do;
188 proc http method="DELETE" url="&base_uri&fileuri" &oauth_bearer;
189 headers
190 %if &grant_type=authorization_code %then %do;
191 "Authorization"="Bearer &&&access_token_var"
192 %end;
193 "Accept"="*/*";
194 run;
195 %put &sysmacroname DELETE &base_uri&fileuri;
196 %if &SYS_PROCHTTP_STATUS_CODE ne 204 %then %do;
197 %put &=SYS_PROCHTTP_STATUS_CODE &=SYS_PROCHTTP_STATUS_PHRASE;
198 %end;
199%end;
200
201%local url mimetype ext;
202%let url=&base_uri/files/files?parentFolderUri=&self_uri;
203%let ext=%upcase(%trim(%scan(&name,-1,.)));
204
205/* Get Viya file-extension details into some macro variables */
206%mv_getViyaFileExtParms(&ext
207 ,propertiesVar=viyaProperties
208 ,typeDefNameVar=viyaTypeDefName
209 ,mdebug=&mdebug);
210
211/* fetch job info */
212%local fname1;
213%let fname1=%mf_getuniquefileref();
214proc http method='POST' out=&fname1 &oauth_bearer in=&fref
215 %if "&ctype" = "0" %then %do;
216 %let mimetype=%mf_mimetype(&ext);
217 ct="&mimetype"
218 %end;
219 %else %do;
220 ct="&ctype"
221 %end;
222
223 /* typeDefName */
224 %if not %mf_isBlank(&viyaTypeDefName) %then %do;
225 url="&url%str(&)typeDefName=&viyaTypeDefName";
226 %end;
227 %else %do;
228 %if "&ext"="HTM" or "&ext"="HTML" or "&ext"="XHTML" %then %do;
229 url="&url%str(&)typeDefName=file_html";
230 %end;
231 %else %do;
232 %if "&ext"="CSS" or "&ext"="JS" or "&ext"="PNG" or "&ext"="SVG" %then %do;
233 url="&url%str(&)typeDefName=file_%lowcase(&ext)";
234 %end;
235 %else %do;
236 url="&url";
237 %end;
238 %end;
239 %end;
240
241 headers "Accept"="application/json"
242 %if &grant_type=authorization_code %then %do;
243 "Authorization"="Bearer &&&access_token_var"
244 %end;
245 "Content-Disposition"=
246 %if "&ext"="SVG" or "&ext"="HTML" %then %do;
247 "filename=""&name"";"
248 %end;
249 %else %do;
250 "&contentdisp filename=""&name""; name=""&name"";"
251 %end;
252 ;
253run;
254%if &mdebug=1 %then %put &sysmacroname POST &=url
255 &=SYS_PROCHTTP_STATUS_CODE &=SYS_PROCHTTP_STATUS_PHRASE;
256%mp_abort(iftrue=(&SYS_PROCHTTP_STATUS_CODE ne 201)
257 ,mac=MV_CREATEFILE
258 ,msg=%str(&SYS_PROCHTTP_STATUS_CODE &SYS_PROCHTTP_STATUS_PHRASE)
259)
260
261%local libref2;
262%let libref2=%mf_getuniquelibref();
263libname &libref2 JSON fileref=&fname1;
264/* Grab the follow on link */
265data &outds;
266 set &libref2..links end=last;
267 if rel='createChild' then do;
268 &dbg put (_all_)(=);
269 end;
270run;
271
272/* URI of the created file */
273%let fileuri=%trim(%mfv_getpathuri(&path/&name));
274
275/* If properties were found then patch the file to include them */
276%if not %mf_isBlank(%superq(viyaProperties)) %then %do;
277 /* Wrap the properties object in a root object also containing the file name */
278 %local viyapatch;
279 %let viyapatch = %sysfunc(pathname(work))/%mf_getuniquename(prefix=patch_json_);
280 data _null_;
281 length line $32767;
282 file "&viyapatch" lrecl=32767;
283 put '{ "name": "' "&name" '",';
284 line = cat('"properties": ',symget("viyaProperties"));
285 put line;
286 put '}';
287 stop;
288 run;
289
290 %if &mdebug=1 %then %do;
291 data _null_;
292 if (_n_ eq 1) then put 'DEBUG: ** PATCH JSON **';
293 infile "&viyapatch" end=last;
294 input;
295 put _infile_;
296 run;
297 %end;
298
299 /* And apply the properties to the newly created file, using the PATCH method */
300 %let fref=%mf_getuniquefileref();
301 filename &fref "&viyapatch";
302 %let url=&base_uri&fileuri;
303
304 proc http method='PATCH' oauth_bearer=sas_services in=&fref
305 url="&url";
306 headers "Accept"="application/json"
307 "Content-Type"="application/json"
308 "If-Match"="*";
309 %if &mdebug=1 %then %do;
310 debug level=2;
311 %end;
312 run;
313 %if &mdebug=1 %then %put &sysmacroname PATCH &=url
314 &=SYS_PROCHTTP_STATUS_CODE &=SYS_PROCHTTP_STATUS_PHRASE;
315 %mp_abort(iftrue=(&SYS_PROCHTTP_STATUS_CODE ne 200)
316 ,mac=MV_CREATEFILE
317 ,msg=%str(&SYS_PROCHTTP_STATUS_CODE &SYS_PROCHTTP_STATUS_PHRASE)
318 )
319%end;
320
321%put &sysmacroname: &base_uri&fileuri;
322%put /SASJobExecution?_file=&path/&name;%put;
323
324%if &mdebug=0 %then %do;
325 /* clear refs */
326 filename &fname1 clear;
327 filename &fref clear;
328 libname &libref2 clear;
329%end;
330
331%mp_abort(
332 iftrue=(&syscc ne 0),
333 msg=Cannot leave &sysmacroname with syscc=&syscc
334)
335
336%mend mv_createfile;