How can I read multipart/form-data from a HTTP Post request in my rest service?
Hello everyone!
I am receiving a HTTP multipart/form-data request into my rest service.
How can I read the values for each Key in the form?
The key "Profile" is sent to my service as a String data type.
The code I have below does not seem to work, where I try to read the Key profile in the form.
I appreciate all the help I can get! :)
Product version: IRIS 2023.3
See the class documentation
Hello! I have read it, and tried multiple things but nothing seems to work :(
set vProfile = $Get(%request.Data("profile")) set vProfile = %request.GetMimeData("profile")
I have tried these already:
set vProfile = %request.Get("profile")
set vProfile = $Get(%request.MimeData("profile"))
and
Hi Emil,
Have you tried
set vProfile = $Get(%request.MimeData("profile",1))
Hello! Yes I tried that aswell. Still returns an empty value :(
Maybe you didn't read it carefully enough...
/// the documentation say clearly: /// /// %request.Data(itemName, itemIndex) /// set vProfile1 = $Get(%request.Data("profile",1)) // the first value set vProfile2 = $Get(%request.Data("profile",2)) // the second value /// etc. /// or you use a loop /// kill value ser value=0 set idx=$order(%request.Data("profile",idx)) while idx]"" { set value($increment(value))=%request.Data("profile",idx) set idx=$order(%request.Data("profile",idx) } /// value = item count /// value(i) = i-th value
"Profile" is one of the keys in the form. I have tried this: set vProfile = $Get(%request.Data("profile",1), but it only returned an empty value :(
And you are certain, the correct name is "profile"?
yes, I am 100% sure. Don't really know where it has gone wrong.
Double checked postman just to be sure.
Is Your class extend % CSP.REST? OR extend EnsLib.REST. Service?
Hello! My class extends %CSP.REST :)
HI
What is the value of %request.ContentType
It says that %request.ContentType is "multipart/form-data"
It says that %request.ContentType is "multipart/form-data"
I think maybe we can give it a try like this
set temp=$o(%request.Data(""))
while temp'=""
{
w temp,":",%request.Data(temp,1),!
set temp=$o(%request.Data(temp))
}
Quit $$$OK
Hello! It still does not seem to retrieve anything :(. Just an empty string
But thanks alot for the code example, I really appreciate it! :)
Just a curious question, do you talk about a form with encoding? Something like this
<form method="post" enctype="multipart/form-data" ...> ... </form>
If yes, I think WRC will be your friend. In any case, I have never worked with such type of encoding. Maybe someone else?
Hello! It is not an encoded form. :( You might be right about WRC being able to help out!
Emil, if the request is not coming from a form with the enctype set to multipart/form-data, can you give us an example of how the request is being created? Maybe the issue is that the request has not been created properly.
Can you provide the full class? Including what it extends and so forth? Also the code of where you construct and send the request.
The following is a working example of uploading a file using a CSP Page.
Class Test.FileUpload Extends %CSP.Page { ClassMethod OnPage() As %Status { &html<<html> <head> </head> <body>> If %request.Method = "POST" { Set tFile = ##class(%Stream.FileBinary).%New() Set tSC = tFile.LinkToFile("C:\Tmp\" _ %request.MimeData("FileStream",1).FileName) If 'tSC { Write !,"Upload Failed" } Else { Do tFile.CopyFrom(%request.MimeData("FileStream",1)) Set tSC = tFile.%Save() If 'tSC { Write !,"Upload Failed" Do tFile.%Close() } Else { Write !,"File Posted",! } } } &html< <h2>Upload a File</h2> <form enctype="multipart/form-data" method="post" action=""> Enter a file to upload here: <input type=file size=30 name=FileStream> <hr /> <ul><input type="submit" value="Upload file"></ul> </form> </body> </html>> Quit $$$OK } }
Hello! :) Yes, I did manage to upload a file using similar code. What doesn't work is actually not being able to read strings that are sent via the form-data to my service. The Key that is being sent in the form-data, via postman, is "Profile" and the value of the key is "TEST". So far I can't manage to log the value "TEST". :(
I think it shouldn't be "profile", it should be the attribute value name.
Hello! :) The request that is being sent to my rest-service via postman has one key in the form which is "Profile". The Value of "Profile" is "TEST". But I cannot get my service to log "TEST". By attribute do you mean the Value of the key "Profile"? :)
Can you post the raw request message of Postman here please?
Or the complete request sent, including the headers?
Here is an example of this concept working. On Ensemble, but should be the same for IRIS.
Note that I configured password authentication on the web application and set up Authentication on Postman.
Code:
Class Tests.RESTFormData Extends %CSP.REST { ClassMethod Test() As %Status { w "Posting: ",$Get(%request.Data("Posting",1)) q 1 } XData UrlMap { <Routes> <Route Url="/" Method="POST" Call="Test" /> </Routes> } }
Web Application Config:
Postman:
Okay! So what finally solved it was a discussion with the WRC support.
Within the Postman request, and the form-data; Content-type was specified as text/plain on each part of the form. That is why %request.Data("profile") wouldn't work at first. The content of each part of the form gets sent into the REST-service as a stream.
With this said, instead I had to use this code which finally worked:
set profileStream = %request.GetMimeData("profile")
set vProfile = profileStream.Read()
However, one thing worth noting is that when I did not specify content-type for each part of the form-data, then the original code I used worked: set vProfile = $Get(%request.Data("profile")) .
Thanks to WRC and everyone here who tried to help! :)