0 votes

Hello,
I'm trying to upload an image to the server but I keep getting a bad request response.

On Postman, the request's body is set to "form-data" with 2 fields, ID and the file to upload. Also, the request has a bearer token in its header. The request works properly there.

I've tried using HttpRequest with a key value body, first value pointing to the string id and the second pointing to an Image. I tried also passing image.data["data"] or passing Marshalls base64.

var body = {
    "id": _id,
    "file": image 
}

I've also tried HttpClient with a PoolByteArray as follows:

var headers = [
"Authorization : Bearer %s" % Token,
"Content-Length: " + str(content.size()),   
"Content-Type: multipart/form-data, boundary=------WebKitFormBoundary7MA4YWxkTrZu0gW"
]

var body = PoolByteArray()
body.append("------WebKitFormBoundary7MA4YWxkTrZu0gW\n")
body.append("Content-Disposition: form-data; name=\"file\"; filename=\"Treasure.png\"\n")
body.append("Content-Type: image/png\n\n")
body.append_array(content)
body.append("\n------WebKitFormBoundary7MA4YWxkTrZu0gW\n")
body.append("Content-Disposition: form-data; name=\"id\"\n\n")
body.append(str(_id))
body.append("\n------WebKitFormBoundary7MA4YWxkTrZu0gW")

I'm sure I'm doing something wrong but I haven't really found an example to upload a file while having another parameter to pass.

Any help or guidance?
Thanks in advance!

Godot version 3.4.3
in Engine by (27 points)
retagged by

1 Answer

0 votes
Best answer

I managed to fix it after a combined effort from the community.

I had multiple issues:

1- I had an extra space in Authorization header and the ":", so it should be "Authorization: ..." instead of "Authorization : ..."

2- Content-Length should be the full length of the body and not only the content

3- I changed the boundary as dashes are not defined in the "boundary" and I used 2 dashes to define the boundary part in the body

4- I'm not sure if it's necessary but I ended up converting every line to UTF 8 and escaping the buffer too

5- I added Content-Transfer-Encoding: base64 to my image body part

So the final code should be something like this:

var body = PoolByteArray()
body.append_array("--BodyBoundaryHere".to_utf8())
body.append_array("\r\nContent-Disposition: form-data; name=\"file\"; filename=\"Treasure.png\"\r\n".to_utf8())
body.append_array("Content-Type: image/png\r\n".to_utf8())
body.append_array("Content-Transfer-Encoding: base64\r\n".to_utf8())
body.append_array("\r\n".to_utf8())
body.append_array(Marshalls.raw_to_base64(content).http_escape().to_utf8())
body.append_array("\r\n".to_utf8())
body.append_array("--BodyBoundaryHere".to_utf8())
body.append_array("\r\nContent-Disposition: form-data; name=\"id\"\r\n".to_utf8())
body.append_array("\r\n".to_utf8())
body.append_array(str(_id).to_utf8())
body.append_array("\r\n".to_utf8())
body.append_array("--BodyBoundaryHere--".to_utf8())

var headers = [
    "Authorization: Bearer %s" % Token,
    "Content-Length: " + str(body.size()),
    "Content-Type: multipart/form-data; boundary=\"BodyBoundaryHere\""
    ]

I hope this will help other people as well!!

by (27 points)
Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to webmaster@godotengine.org with your username.