Question
· Jan 8

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
Discussion (26)3
Log in or sign up to continue

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

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
}

}

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! :)