Question Emil Odobasic · Jan 8, 2024

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

Comments

Emil Odobasic  Jan 8, 2024 to Julius Kavay

Hello! I have read it, and tried multiple things but nothing seems to work :( 
I have tried these already: 
set vProfile = %request.Get("profile")
set vProfile = $Get(%request.Data("profile"))
set vProfile = $Get(%request.MimeData("profile"))
and 
set vProfile = %request.GetMimeData("profile")

0
Danny Wijnschenk  Jan 8, 2024 to Emil Odobasic

Hi Emil,

Have you tried
set vProfile $Get(%request.MimeData("profile",1))
 

0
Emil Odobasic  Jan 8, 2024 to Danny Wijnschenk

Hello! Yes I tried that aswell. Still returns an empty value :(

0
Julius Kavay  Jan 8, 2024 to Emil Odobasic

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 valueset vProfile2 = $Get(%request.Data("profile",2)) // the second value/// etc./// or you use a loop///kill value
ser value=0set 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
0
Emil Odobasic  Jan 8, 2024 to Julius Kavay

"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 :(

0
Julius Kavay  Jan 8, 2024 to Emil Odobasic

And you are certain,  the correct name is "profile"?

0
Emil Odobasic  Jan 8, 2024 to Julius Kavay

yes, I am 100% sure. Don't really know where it has gone wrong.
Double checked postman just to be sure.

0
Shanshan Yu · Jan 8, 2024

Is Your class extend % CSP.REST? OR extend EnsLib.REST. Service?

0
Emil Odobasic  Jan 9, 2024 to Shanshan Yu

Hello! My class extends %CSP.REST :)

0
Shanshan Yu  Jan 9, 2024 to Emil Odobasic

HI 

  What is the value of  %request.ContentType

0
Emil Odobasic  Jan 9, 2024 to Shanshan Yu

It says that %request.ContentType is "multipart/form-data"

0
Emil Odobasic  Jan 9, 2024 to Shanshan Yu

It says that %request.ContentType is "multipart/form-data"

0
Shanshan Yu  Jan 9, 2024 to Emil Odobasic

HI,

I think maybe we can give it a try like this

set temp=$o(%request.Data(""))
while temp'=""
{
temp,":",%request.Data(temp,1),!
set temp=$o(%request.Data(temp))
}
Quit $$$OK

0
Emil Odobasic  Jan 10, 2024 to Shanshan Yu

Hello! It still does not seem to retrieve anything :(. Just an empty string

0
Emil Odobasic  Jan 10, 2024 to Shanshan Yu

But thanks alot for the code example, I really appreciate it! :)

0
Julius Kavay · Jan 9, 2024

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?

0
Emil Odobasic  Jan 10, 2024 to Julius Kavay

Hello! It is not an encoded form. :( You might be right about WRC being able to help out!

0
David Hockenbroch  Jan 11, 2024 to Emil Odobasic

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.

0
Stefan Cronje · Jan 11, 2024

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><formenctype="multipart/form-data"method="post"action="">
    Enter a file to upload here: <inputtype=filesize=30name=FileStream><hr /><ul><inputtype="submit"value="Upload file"></ul></form></body></html>>Quit$$$OK
}

}
0
Emil Odobasic  Jan 12, 2024 to Stefan Cronje

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". :(

0
Kavay Lylius · Jan 12, 2024

I think it shouldn't be "profile", it should be the attribute value name.

0
Emil Odobasic  Jan 12, 2024 to Kavay Lylius

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"? :) 

0
Stefan Cronje  Jan 12, 2024 to Emil Odobasic

Can you post the raw request message of Postman here please?
Or the complete request sent, including the headers?

0
Stefan Cronje  Jan 12, 2024 to Emil Odobasic

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))
	q1
}

XData UrlMap
{
<Routes>
	<Route Url="/" Method="POST" Call="Test" />
	</Routes>
}

}

Web Application Config:

 

Postman:

 

0
Emil Odobasic · Jan 29, 2024

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

0