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 
149 options 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 )
162 data _null_;
163  set &folderds;
164  call symputx('self_uri',self_uri,'l');
165 run;
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();
197 proc 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  ;
225 run;
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();
234 libname &libref2 JSON fileref=&fname1;
235 /* Grab the follow on link */
236 data &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;
242 run;
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;