I am trying to upload an excel workbook to a repository called, Documentum. I have never used the PROC HTTP command before.
I do have access to the url due to my being able to use Python to perform this very task.
I am getting the following error: HTTP/1.1 400 Bad Request.
Once I resolve this, I will be using a different authentication scheme.
Here is the sas code running from the Unix environment:
filename reqst "/home/sasuser/XXXXX/phttp/reqst.txt"; filename resp "/home/sasuser/XXXXX/phttp/resp.txt"; filename hdrout "/home/sasuser/XXXXX/phttp/hdrout.txt"; filename hdrin "/home/sasuser/XXXXX/phttp/hdrin.txt"; filename datfile "/home/sasuser/nbkqyyn/phttp/XXXPRD034XXXXX.xlsx"; Proc HTTP WEBUSERNAME="userID" WEBPASSWORD="password" AUTH_BASIC url="https://baseXXX/dctm-rest/repositories/ECMSGCB/folders/FOLDERIDXXX/documents/" method="POST" in=datfile out=resp headerin=hdrin headerout=hdrout /* CT="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; */ CT="application/vnd.emc.documentum+json"; /* headers "Accept"="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";*/ DEBUG LEVEL=2 ; run; %put &=sys_prochttp_status_code.; %put &=sys_prochttp_status_phrase.; filename hdrin clear; filename reqst clear; filename resp clear; filename hdrout clear; filename datfile clear;
Here are the contents of the hdrin.txt file:
object_name: XXXPRD034XXXXX.xlsx r_object_type:ecap_trad_documents CT:application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
Here are the contents of the hdrout.txt file:
HTTP/1.1 400 Bad Request Date: Fri, 15 May 2020 16:17:24 GMT X-Powered-By: Servlet/3.0 X-Content-Type-Options: nosniff X-XSS-Protection: 1; mode=block Cache-Control: no-cache, no-store, max-age=0, must-revalidate Pragma: no-cache Expires: 0 X-Frame-Options: DENY X-Cnection: close Transfer-Encoding: chunked Content-Type: application/vnd.emc.documentum+json;charset=UTF-8 Content-Language: en-US Strict-Transport-Security: max-age=31536000
Here are the contents of the resp.txt file:
{"status":400,"code":"E_INPUT_MESSAGE_NOT_READABLE","message":"The input message is not readable.","details":"Error in parsing the JSON into object class: class com.emc.documentum.rest.model.DocumentObject;Unrecognized token 'PK\u0003\u0004\u0014\u0000\u0006\u0000\b\u0000\u0000\u0000': was expecting ('true', 'false' or 'null')\n at [Source: (PushbackInputStream); line: 1, column: 14]","id":"1d9b6f0e-7682-4c94-891b-345395de0dde"}
Thoughts? Thanks!
Glad I could help.
This is actually a pretty good model for most cloud storage APIs.
The first call is to create the object, which is typically described by a json input.
The next call is to actually upload the data.
Hi @nizguyk,
Your code has conflicting values for CT (content type). You're wanting to post an Excel file, but you're passing:
CT="application/vnd.emc.documentum+json";
This might be confusing the API endpoint.
Not sure what Python library you're using, but do you have a cURL command that works? That is usually easy to transcribe to PROC HTTP, if you could share something like that.
I wonder if this is a two-step process: first step to create an object in the system (and return an ID for that), and second step to post the actual content of the file to the object with the ID from step 1.
Chris
I was sent the Python code that was working and from that I can see that 2 calls are needed.
The first call creates the Object. This is a JSON file that contains that name and type of document.
The next call actual uploads the data.
This code should be close to what you need:
%let full_file_name=DART_Report_Template.xlsx; %let repository_document_type=ecap_trad_documents; *%let document_url=https://XXXXXX/dctm-rest/repositories/ECAPID/folders/FOLDERID/documents; %let document_url=http://httpbin.org/post; /* Make the intial HTTP request that creates the object in which content will be uploaded */ filename resp TEMP; proc http url="&document_url." method="POST" USERNAME="USERID" PASSWORD="PASSWORD" AUTH_BASIC in="{""object_name"": ""&full_file_name."", ""r_object_type"": ""&repository_document_type."" }" out=resp ct="application/vnd.emc.documentum+json"; run; /* Check to make sure the call succeeded */ %if &SYS_PROCHTTP_STATUS_CODE. ne 201 %then %do; %put ERROR: Expected 201, but received &SYS_PROCHTTP_STATUS_CODE.; %abort; %end; /* Parse the JSON response and get the link to upload the content */ libname doc json fileref=resp; data _null_; set resp.links(where=(rel='contents')); call symputx("href",tranwrd(href,'&','%nrstr(&)'),'G'); stop; run; /* Now load the data */ filename resp2 TEMP; filename datfile "/home/sasuser/nbkqyyn/phttp/XXXPRD034XXXXX.xlsx"; proc http url="&href." method="POST" ct = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" in=datfile out=resp2; run;
Hello. Thank you for the replies.
I am not sure why, but I am getting the following error message after the 1st post call:
ordinal_root: 1 status: 409 code : "E_CREATE_CONTENT_NOT_ALLOWED_TO _OVERWRITE" message: "The content or rendition creation failed because the overwrite parameter is set to false." details: "(DM_SYSOBJECT_E_CANT_OVERWRITE_EXISTING_CONTENT) DM_SYSOBJECT_E_CANT_OVERWRITE_EXISTING_CONTENT"
I tried adding the full pathname to the full_file_name variable.
I tried re-running it with a different name in the unix directory.
But I keep getting that HTTP/1.1 409 Conflict error message.
Is there some property that the Documentum admin needs to change?
Normally, when we run the Python code to upload the same file, a new file entry is noted, and the file name is the same, but it has a new create/modification date, which I assume means it is keeping history.
Thoughts? Thanks!
Hello.
BIG kudos go out to Joseph Henry on this who assisted me.
I had read several of his papers in regards to PROC HTTP, and he is indeed an excellent resource.
I was finally able to load an .xlsx file to Documentum (repository somewhat similar to SharePoint).
The code is below. I have had to mask some of the values due to security concerns.
You will need to work with your Documentum admin to get the appropriate access permissions, as well as the initial link to use in order to get your code to work.
options mlogic mprint symbolgen; /* Purpose: Upload .xlsx workbook file to Documentum */ /* 2 macros below are specific to Documentum; work with the Docu admin on this */ %Let repository_document_type=xxx_trad_documenxx; %Let Document_URL=https://XXXXXXX/dctm-rest/repositories/XXXXX/folders/0b01869c802d3f45/documents; %Let file_name =Workbookname.xlsx; /* Linux path names */ Filename resp1 "/home/sasuser/xxxx/phttp/resp1.txt"; Filename resp2 "/home/sasuser/xxxx/phttp/resp2.txt"; Filename hdrout "/home/sasuser/xxxx/phttp/hdrout.txt"; Filename datfile "/home/sasuser/xxxx/phttp/WorkBookName.xlsx"; /* Make the intial HTTP request that creates the object in which the content will be uploaded */ PROC HTTP URL="&Document_URL." Method="POST" USERNAME="userID" PASSWORD="Password" AUTH_BASIC IN="{""properties"":{""object_name"": ""&file_name."", ""r_object_type"": ""&repository_document_type."" }}" OUT=resp1 HEADEROUT=hdrout CT="application/vnd.emc.documentum+json"; DEBUG LEVEL=3; Run; %put &=sys_prochttp_status_code.; %put &=sys_prochttp_status_phrase.; /* Check to make sure the call succeeded */ %IF &SYS_PROCHTTP_STATUS_CODE. NE 201 %Then %Do; %Put ERROR_CODE: Expected 201, but received &SYS_PROCHTTP_STATUS_CODE.; %Put ERROR_DESC: &SYS_PROCHTTP_STATUS_PHRASE. ; %Abort; %End; /* Parse the JSON response and get the link to upload the content from the resp1 file reference. Resp1 will contain many key: value pair values (mainly links) */ Libname doc JSON Fileref=resp1; Data _Null_; Set doc.links(where=(rel='contents')); Call Symputx("href",tranwrd(href,'&','%nrstr(&)'),'G'); Stop; Run; %put &=href; /* debugging files proc datasets lib=doc; run; quit; proc print data=doc.alldata; run; proc print data=doc.root; run; data CheckLinks; set doc.links; run; */ /* Now load the .xlsx workbook */ PROC HTTP URL="&href." Method="POST" USERNAME="userID" PASSWORD="password" CT = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" IN=datfile OUT=resp2; DEBUG LEVEL=3; run; %put &=sys_prochttp_status_code.; %put &=sys_prochttp_status_phrase.; /* clean up */ Filename resp1 Clear; Filename resp2 Clear; Filename hdrout Clear; Filename datfile Clear; Libname doc Clear;
Glad I could help.
This is actually a pretty good model for most cloud storage APIs.
The first call is to create the object, which is typically described by a json input.
The next call is to actually upload the data.
Are you ready for the spotlight? We're accepting content ideas for SAS Innovate 2025 to be held May 6-9 in Orlando, FL. The call is open until September 25. Read more here about why you should contribute and what is in it for you!
Learn how use the CAT functions in SAS to join values from multiple variables into a single value.
Find more tutorials on the SAS Users YouTube channel.