I have seen almost all answers in relation to this suggest to use some variant of FormData
within nodejs to build a multipart form.
I wish to achieve the same without using the FormData
library, but instead just using request headers and a string for the request body.
Only one answer hints at how this can be achieved, but the solution uses a stringify function on the string payload so I am not sure how the correct stringified body should look like.
Regardless, I have gotten this far;
import { RequestOptions } from "http"
const path: 'url/'
const method: 'POST'
const body = `--BOUNDARY
\nContent-Disposition: form-data; name="file"; filename="test.txt"
\nContent-Type: text/plain
\nThis is the content of the file
\n--BOUNDARY
\nContent-Disposition: form-data; name="form-field-one"
\nexample1
\n--BOUNDARY
\nContent-Disposition: form-data; name="form-field-two"
\nexample2
\n--BOUNDARY--`
const headers = {
'content-type': 'multipart/form-data; boundary=BOUNDARY',
'content-length': String(Buffer.byteLength(body))
}
const options = {
path,
method,
headers,
body
}
const response = await execute(options)
I cannot create a fully minimal reproduction as I am not permitted to post the execute function contents, but I can describe the function signature I need to use (which is why I need to use this string approach).
For what its worth, i think the function is simply using the basic builtin nodejs http
library.
import { RequestOptions } from "http"
const execute = async (options: RequestOptions): Promise<any> => { ... }
I get an error using this, but the error is not helpful at all due to the internals of the function.
Regardless, I believe it should be possible to replicate sending a multi-part form (with file and form fields) using just the body and headers of a POST request without an additional library to transform the data of the body.
My string is a modified output from a successful Postman request multipart form request.
Can someone point out what I am doing incorrectly?
CodePudding user response:
Several points:
- Every line in your
`...`
already ends with a newline, but the next starts with\n
, which contributes another newline, leading to an unwanted blank line. - You do need a blank line between the headers and content.
- Lines must end with CRLF, so you must add a
\r
as the last character on each line.
Try this:
const body = `--BOUNDARY\r
Content-Disposition: form-data; name="file"; filename="test.txt"\r
Content-Type: text/plain\r
\r
This is the content of the file\r
--BOUNDARY\r
Content-Disposition: form-data; name="form-field-one"\r
\r
example1\r
--BOUNDARY\r
Content-Disposition: form-data; name="form-field-two"\r
\r
example2\r
--BOUNDARY--`
CodePudding user response:
Certainly! It looks like you're trying to build a multipart form request body manually as a string. There are a few issues with the string you've provided:
The string is missing the final newline before the final --BOUNDARY-- boundary marker. The Content-Type header for the file should specify the type of the file being uploaded. In this case, you've specified text/plain, but you'll want to use the appropriate MIME type for the file you're trying to upload. The Content-Disposition headers for the form fields should have a value parameter, like this:
Content-Disposition: form-data; name="form-field-one"; value="example1" Here's an example of how the body string should look like: const body = `--BOUNDARY Content-Disposition: form-data; name="file"; filename="test.txt" Content-Type: text/plain
This is the content of the file --BOUNDARY Content-Disposition: form-data; name="form-field-one"; value="example1"
--BOUNDARY Content-Disposition: form-data; name="form-field-two"; value="example2"
--BOUNDARY-- `;
Note that each part of the form is separated by a boundary marker, and each part should have a blank line after the headers.
I hope this helps! Let me know if you have any questions.
CodePudding user response:
It is possible to create a multipart form POST request using just the body and headers of the request. However, it is a bit more involved than simply setting the Content-Type header to multipart/form-data and including the data in the body of the request.
Here's a step-by-step guide on how you can create a multipart form POST request using just the body and headers:
Choose a boundary string that will be used to separate the different parts of the request. The boundary should be a unique string that does not appear in the data that you are sending. In your code, you have chosen BOUNDARY as the boundary string.
Set the Content-Type header to multipart/form-data; boundary=BOUNDARY, where BOUNDARY is the boundary string you chose in step 1.
Begin the body of the request with the boundary string, followed by a newline character. For example:
--BOUNDARY\n
For each field in the form, add a Content-Disposition header and the field value. The Content-Disposition header should include the name of the field, as well as any other necessary information (such as filename for file fields). For example:
Content-Disposition: form-data; name="form-field-one"\n
example1\n
- For file fields, include the Content-Type header as well as the contents of the file. For example
Content-Disposition: form-data; name="file"; filename="test.txt"\n
Content-Type: text/plain\n
This is the content of the file\n
- After each field, include the boundary string followed by a newline character. For example:
--BOUNDARY\n
- After the last field, include the boundary string followed by -- to indicate the end of the request.
So, the complete body of the request should look something like this:
--BOUNDARY
Content-Disposition: form-data; name="file"; filename="test.txt"
Content-Type: text/plain
This is the content of the file
--BOUNDARY
Content-Disposition: form-data; name="form-field-one"
example1
--BOUNDARY
Content-Disposition: form-data; name="form-field-two"
example2
--BOUNDARY--