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
212/* fetch job info */
213%local fname1;
214%let fname1=%mf_getuniquefileref();
215proc http method='POST' out=&fname1 &oauth_bearer in=&fref
216 %if "&ctype" = "0" %then %do;
217 %let mimetype=%mf_mimetype(&ext);
218 ct="&mimetype"
219 %end;
220 %else %do;
221 ct="&ctype"
222 %end;
223
224 /* typeDefName */
225 %if not %mf_isBlank(&viyaTypeDefName) %then %do;
226 url="&url%str(&)typeDefName=&viyaTypeDefName";
227 %end;
228 %else %do;
229 %if "&ext"="HTM" or "&ext"="HTML" or "&ext"="XHTML" %then %do;
230 url="&url%str(&)typeDefName=file_html";
231 %end;
232 %else %do;
233 %if "&ext"="CSS" or "&ext"="JS" or "&ext"="PNG" or "&ext"="SVG" %then %do;
234 url="&url%str(&)typeDefName=file_%lowcase(&ext)";
235 %end;
236 %else %do;
237 url="&url";
238 %end;
239 %end;
240 %end;
241
242 headers "Accept"="application/json"
243 %if &grant_type=authorization_code %then %do;
244 "Authorization"="Bearer &&&access_token_var"
245 %end;
246 "Content-Disposition"=
247 %if "&ext"="SVG" or "&ext"="HTML" %then %do;
248 "filename=""&name"";"
249 %end;
250 %else %do;
251 "&contentdisp filename=""&name""; name=""&name"";"
252 %end;
253 ;
254run;
255%if &mdebug=1 %then %put &sysmacroname POST &=url
256 &=SYS_PROCHTTP_STATUS_CODE &=SYS_PROCHTTP_STATUS_PHRASE;
257%mp_abort(iftrue=(&SYS_PROCHTTP_STATUS_CODE ne 201)
258 ,mac=MV_CREATEFILE
259 ,msg=%str(&SYS_PROCHTTP_STATUS_CODE &SYS_PROCHTTP_STATUS_PHRASE)
260)
261
262%local libref2;
263%let libref2=%mf_getuniquelibref();
264libname &libref2 JSON fileref=&fname1;
265/* Grab the follow on link */
266data &outds;
267 set &libref2..links end=last;
268 if rel='createChild' then do;
269 &dbg put (_all_)(=);
270 end;
271run;
272
273/* URI of the created file */
274%let fileuri=%trim(%mfv_getpathuri(&path/&name));
275
276/* If properties were found then patch the file to include them */
277%if not %mf_isBlank(%superq(viyaProperties)) %then %do;
278 /* Wrap the properties object in a root object also containing the filename */
279 %local viyapatch;
280 %let viyapatch=%sysfunc(pathname(work))/%mf_getuniquename(prefix=patch_json_);
281 data _null_;
282 length line $32767;
283 file "&viyapatch" lrecl=32767;
284 put '{ "name": "' "&name" '",';
285 line = cat('"properties": ',symget("viyaProperties"));
286 put line;
287 put '}';
288 stop;
289 run;
290
291 %if &mdebug=1 %then %do;
292 data _null_;
293 if (_n_ eq 1) then put 'DEBUG: ** PATCH JSON **';
294 infile "&viyapatch" end=last;
295 input;
296 put _infile_;
297 run;
298 %end;
299
300 /* Apply the properties to the newly created file, using the PATCH method */
301 %let fref=%mf_getuniquefileref();
302 filename &fref "&viyapatch";
303 %let url=&base_uri&fileuri;
304
305 proc http method='PATCH' oauth_bearer=sas_services in=&fref
306 url="&url";
307 headers "Accept"="application/json"
308 "Content-Type"="application/json"
309 "If-Match"="*";
310 %if &mdebug=1 %then %do;
311 debug level=2;
312 %end;
313 run;
314 %if &mdebug=1 %then %put &sysmacroname PATCH &=url
315 &=SYS_PROCHTTP_STATUS_CODE &=SYS_PROCHTTP_STATUS_PHRASE;
316 %mp_abort(iftrue=(&SYS_PROCHTTP_STATUS_CODE ne 200)
317 ,mac=MV_CREATEFILE
318 ,msg=%str(&SYS_PROCHTTP_STATUS_CODE &SYS_PROCHTTP_STATUS_PHRASE)
319 )
320%end;
321
322%put &sysmacroname: &base_uri&fileuri;
323%put /SASJobExecution?_file=&path/&name;%put;
324
325%if &mdebug=0 %then %do;
326 /* clear refs */
327 filename &fname1 clear;
328 filename &fref clear;
329 libname &libref2 clear;
330%end;
331
332%mp_abort(
333 iftrue=(&syscc ne 0),
334 msg=Cannot leave &sysmacroname with syscc=&syscc
335)
336
337%mend mv_createfile;