Your SAS programs, embedded in web apps and elsewhere

Upload file to a stored process from python/php/other backend

Reply
Contributor
Posts: 33

Upload file to a stored process from python/php/other backend

[ Edited ]

I've seemingly read through all the threads and documentation with no avail.

 

I'd like to send a csv from one non-SAS server to a SAS server through a stored process which will return some output. This appears to be trivial to do when using non-file parameters, but impossible when using a csv.

 

For instance, assuming a python non-SAS backend, using the requests library I logon and then call the testprint_sp stored process.

base_url = "https://mybaseurl"
login_url = base_url + "/SASLogon/login"
s = requests.Session()
r = s.get(login_url, verify=False)

data = {"username": "uname", "password":"pwd123"}
r = s.post(login_url, data=data)

execute_url = base_url + "/SASStoredProcess/do?_program=/User Folders/my folder/testprint_sp"
data = {'num':20}
r = s.post(execute_url, data=data)

Or after logging on, simply browsing to 

https://mybaseurl/SASStoredProcess/do?_program=/User Folders/my folder/testprint_sp&num=20

This is great but it fails when I try to send a csv.

filename = "D:/Documents/testfile.csv"
files = {'file': ('myfile', open(filename, 'rb'))}
r = s.post(execute_url, data=data, files=files)

 All of the _WEBIN_% macro variables are missing. 

 

Now, there is a workaround which is to build an html form within a sas stored process.

<form action="StoredProcessWebApplicationURL" method="post"
 enctype="multipart/form-data">
<input type="hidden" name="_program" value="/Path/StoredProcessName">
<table border="0" cellpadding="5">
 <tr>
 <th>Choose a file to upload:</th>
 <td><input type="file" name="myfile"></td>
 </tr>
 <tr>
 <td colspan="2" align="center"><input type="submit" value="OK"></td>
 </tr>
</table>

But this adds the extra step of having a client using the form and browsing to a specific file. I'd like the data to be automatically sent to SAS without having an html form built in a SAS procedure.

 

Any help is greatly appreciated.

Frequent Contributor
Posts: 106

Re: Upload file to a stored process from python/php/other backend

Ted,

 

Are you sure you're setting the headers properly in your POST request from Python? The Content Type needs to be set to multipart/form-data.

http://stackoverflow.com/questions/68477/send-file-using-post-from-a-python-script

has an example where the header is set correctly in Python. It also suggests the 'poster' library which seems pretty nifty, rather than doing it all manually.

 

If you submit a form with an upload component from the browser, as per the STP form with input type "file", I think the browser automatically sets the header of Content-type: multipart/form-data. This is how SAS will know that you're uploading a file as part of the post request. Otherwise, the default content type in the header for a POST is set to application/x-www-form-encoded (I think).

 

As per top answer from http://stackoverflow.com/questions/4526273/what-does-enctype-multipart-form-data-mean:

 

When you make a POST request, you have to encode the data that forms the body of the request in some way.

HTML forms provide three methods of encoding.

  • application/x-www-form-urlencoded (the default)
  • multipart/form-data
  • text/plain

Work was being done on adding application/json, but that has been abandoned.

The specifics of the formats don't matter to most developers. The important points are:

When you are writing client-side code, all you need to know is use multipart/form-data when your form includes any <input type="file"> elements.

When you are writing server-side code: Use a prewritten form handling library (e.g. Perl's CGI->param or the one exposed by PHP's $_POST superglobal) and it will take care of the differences for you. Don't bother trying to parse the raw input received by the server.

Never use text/plain.

 

 

Hope this helps.

 

Nik

Ask a Question
Discussion stats
  • 1 reply
  • 498 views
  • 0 likes
  • 2 in conversation