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
73 <h4> Related Macros</h4>
74 @li mv_createfile.sas
75
76**/
77
78%macro mv_createfile(path=
79 ,name=
80 ,inref=
81 ,intype=BINARY
82 ,contentdisp=attachment
83 ,ctype=0
84 ,access_token_var=ACCESS_TOKEN
85 ,grant_type=sas_services
86 ,mdebug=0
87 ,outds=_null_
88 ,force=YES
89 ,swap=0
90 );
91%local dbg;
92%if &mdebug=1 %then %do;
93 %put &sysmacroname entry vars:;
94 %put _local_;
95%end;
96%else %let dbg=*;
97
98%local oauth_bearer;
99%if &grant_type=detect %then %do;
100 %if %symexist(&access_token_var) %then %let grant_type=authorization_code;
101 %else %let grant_type=sas_services;
102%end;
103%if &grant_type=sas_services %then %do;
104 %let oauth_bearer=oauth_bearer=sas_services;
105 %let &access_token_var=;
106%end;
107
108%mp_abort(iftrue=(&grant_type ne authorization_code and &grant_type ne password
109 and &grant_type ne sas_services
110 )
111 ,mac=MV_CREATEFILE
112 ,msg=%str(Invalid value for grant_type: &grant_type)
113)
114
115%mp_abort(iftrue=(%mf_isblank(&path)=1 or %length(&path)=1)
116 ,mac=MV_CREATEFILE
117 ,msg=%str(path value must be provided)
118)
119%mp_abort(iftrue=(%mf_isblank(&name)=1 or %length(&name)=1)
120 ,mac=MV_CREATEFILE
121 ,msg=%str(name value with length >1 must be provided)
122)
123
124/* prep the source file */
125%local fref;
126%let fref=%mf_getuniquefileref();
127
128%if %upcase(&intype)=BINARY %then %let fref=&inref;
129%else %if %upcase(&intype)=BASE64 %then %do;
130 %mp_base64copy(inref=&inref, outref=&fref, action=DECODE)
131%end;
132%else %put %str(ERR)OR: invalid value for intype: &intype;
133
134%if "&swap" ne "0" %then %do;
135 %mp_replace("%sysfunc(pathname(&fref))"
136 ,findvar=%scan(&swap,1,%str( ))
137 ,replacevar=%scan(&swap,2,%str( ))
138 )
139%end;
140
141%if &mdebug=1 %then %do;
142 data _null_;
143 infile &fref lrecl=32767;
144 input;
145 put _infile_;
146 run;
147%end;
148
149options noquotelenmax;
150%local base_uri; /* location of rest apis */
151%let base_uri=%mf_getplatform(VIYARESTAPI);
152
153/* create folder if it does not already exist */
154%local folderds self_uri;
155%let folderds=%mf_getuniquename(prefix=folderds);
156%mv_createfolder(path=&path
157 ,access_token_var=&access_token_var
158 ,grant_type=&grant_type
159 ,mdebug=&mdebug
160 ,outds=&folderds
161)
162data _null_;
163 set &folderds;
164 call symputx('self_uri',self_uri,'l');
165run;
166
167/* abort or delete if file already exists */
168%let force=%upcase(&force);
169%local fileuri ;
170%let fileuri=%mfv_getpathuri(&path/&name);
171%mp_abort(iftrue=(%mf_isblank(&fileuri)=0 and &force ne YES)
172 ,mac=MV_CREATEFILE
173 ,msg=%str(File &path/&name already exists and force=&force)
174)
175
176%if %mf_isblank(&fileuri)=0 and &force=YES %then %do;
177 proc http method="DELETE" url="&base_uri&fileuri" &oauth_bearer;
178 headers
179 %if &grant_type=authorization_code %then %do;
180 "Authorization"="Bearer &&&access_token_var"
181 %end;
182 "Accept"="*/*";
183 run;
184 %put &sysmacroname DELETE &base_uri&fileuri;
185 %if &SYS_PROCHTTP_STATUS_CODE ne 204 %then %do;
186 %put &=SYS_PROCHTTP_STATUS_CODE &=SYS_PROCHTTP_STATUS_PHRASE;
187 %end;
188%end;
189
190%local url mimetype ext;
191%let url=&base_uri/files/files?parentFolderUri=&self_uri;
192%let ext=%upcase(%scan(&name,-1,.));
193
194/* fetch job info */
195%local fname1;
196%let fname1=%mf_getuniquefileref();
197proc http method='POST' out=&fname1 &oauth_bearer in=&fref
198 %if "&ctype" = "0" %then %do;
199 %let mimetype=%mf_mimetype(&ext);
200 ct="&mimetype"
201 %end;
202 %else %do;
203 ct="&ctype"
204 %end;
205 %if "&ext"="HTML" or "&ext"="CSS" or "&ext"="JS" or "&ext"="PNG"
206 or "&ext"="SVG" %then %do;
207 url="&url%str(&)typeDefName=file";
208 %end;
209 %else %do;
210 url="&url";
211 %end;
212
213 headers "Accept"="application/json"
214 %if &grant_type=authorization_code %then %do;
215 "Authorization"="Bearer &&&access_token_var"
216 %end;
217 "Content-Disposition"=
218 %if "&ext"="SVG" or "&ext"="HTML" %then %do;
219 "filename=""&name"";"
220 %end;
221 %else %do;
222 "&contentdisp filename=""&name""; name=""&name"";"
223 %end;
224 ;
225run;
226%if &mdebug=1 %then %put &sysmacroname POST &=url
227 &=SYS_PROCHTTP_STATUS_CODE &=SYS_PROCHTTP_STATUS_PHRASE;
228%mp_abort(iftrue=(&SYS_PROCHTTP_STATUS_CODE ne 201)
229 ,mac=MV_CREATEFILE
230 ,msg=%str(&SYS_PROCHTTP_STATUS_CODE &SYS_PROCHTTP_STATUS_PHRASE)
231)
232%local libref2;
233%let libref2=%mf_getuniquelibref();
234libname &libref2 JSON fileref=&fname1;
235/* Grab the follow on link */
236data &outds;
237 set &libref2..links end=last;
238 if rel='createChild' then do;
239 call symputx('href',quote(cats("&base_uri",href)),'l');
240 &dbg put (_all_)(=);
241 end;
242run;
243
244%put &sysmacroname: &name created at %mfv_getpathuri(&path/&name);%put;
245%put &base_uri/SASJobExecution?_file=&path/&name;%put;
246
247%mend mv_createfile;