Example of Multipart/Form-Data

Example of Multipart/Form-Data

I am wondering if anyone can share with me an example of multipart/form-data that contains:

  1. Some form parameters
  2. Multiple files
4

3 Answers

EDIT: I am maintaining a similar, but more in-depth answer at:

To see exactly what is happening, use nc -l or an ECHO server and an user agent like a browser or cURL.

Save the form to an .html file:

<form action="" method="post" enctype="multipart/form-data">
  <p><input type="text" name="text" value="text default">
  <p><input type="file" name="file1">
  <p><input type="file" name="file2">
  <p><button type="submit">Submit</button>
</form>

Create files to upload:

echo 'Content of a.txt.' > a.txt
echo '<!DOCTYPE html><title>Content of a.html.</title>' > a.html

Run:

nc -l localhost 8000

Open the HTML on your browser, select the files and click on submit and check the terminal.

nc prints the request received. Firefox sent:

POST / HTTP/1.1
Host: localhost:8000
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:29.0) Gecko/20100101 Firefox/29.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Cookie: __atuvc=34%7C7; permanent=0; _gitlab_session=226ad8a0be43681acf38c2fab9497240; __profilin=p%3Dt; request_method=GET
Connection: keep-alive
Content-Type: multipart/form-data; boundary=---------------------------9051914041544843365972754266
Content-Length: 554

-----------------------------9051914041544843365972754266
Content-Disposition: form-data; name="text"

text default
-----------------------------9051914041544843365972754266
Content-Disposition: form-data; name="file1"; filename="a.txt"
Content-Type: text/plain

Content of a.txt.

-----------------------------9051914041544843365972754266
Content-Disposition: form-data; name="file2"; filename="a.html"
Content-Type: text/html

<!DOCTYPE html><title>Content of a.html.</title>

-----------------------------9051914041544843365972754266--

Aternativelly, cURL should send the same POST request as your a browser form:

nc -l localhost 8000
curl -F "text=default" -F "file1=@a.html" -F "file1=@a.txt" localhost:8000

You can do multiple tests with:

while true; do printf '' | nc -l localhost 8000; done
5

Many thanks to @Ciro Santilli answer! I found that his choice for boundary is quite "unhappy" because all of thoose hyphens: in fact, as @Fake Name commented, when you are using your boundary inside request it comes with two more hyphens on front:

Example:

POST / HTTP/1.1
HOST: host.example.com
Cookie: some_cookies...
Connection: Keep-Alive
Content-Type: multipart/form-data; boundary=12345

--12345
Content-Disposition: form-data; name="sometext"

some text that you wrote in your html form ...
--12345
Content-Disposition: form-data; name="name_of_post_request" filename="filename.xyz"

content of filename.xyz that you upload in your form with input[type=file]
--12345
Content-Disposition: form-data; name="image" filename="picture_of_sunset.jpg"

content of picture_of_sunset.jpg ...
--12345--

I found on this w3.org page that is possible to incapsulate multipart/mixed header in a multipart/form-data, simply choosing another boundary string inside multipart/mixed and using that one to incapsulate data. At the end, you must "close" all boundary used in FILO order to close the POST request (like:

POST / HTTP/1.1
...
Content-Type: multipart/form-data; boundary=12345

--12345
Content-Disposition: form-data; name="sometext"

some text sent via post...
--12345
Content-Disposition: form-data; name="files"
Content-Type: multipart/mixed; boundary=abcde

--abcde
Content-Disposition: file; file="picture.jpg"

content of jpg...
--abcde
Content-Disposition: file; file="test.py"

content of test.py file ....
--abcde--
--12345--

Take a look at the link above.

2

There is an example of the multipart data (Angular):

  1. trip-upload.component.html

    Trip:
       <div class="form-group">
         <label for="guide">Guide for the trip:</label>
         <input formControlName="guide" type="file" id="guide" name="guide" (change)="uploadFile($event,'guide')">
       </div>
    
       <div class="form-group">
         <label for="photo">Guide for the trip:</label>
         <input formControlName="photo" type="image" id="photo" name="photo" (change)="uploadFile($event, 'photo')">
       </div>
    
       <div class="form-group">
         <button class="btn">Upload files</button>
       </div>
     </form>
    

2.trip-upload.component.ts

import {Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup } from "@angular/forms";
import { HttpClient } from '@angular/common/http';

@Component({
  selector: 'trip-upload',
  templateUrl: './trip-upload.component.html',
  styleUrls: ['./trip-upload.component.css']
})

export class TripUploadComponent implements OnInit {
  public form: FormGroup;

  constructor(public fb: FormBuilder, private http: HttpClient) {}

  ngOnInit() {
    this.form = this.fb.group({
      name: [''],
      photo: [null],
      guide: [null]
    })
  }

  uploadFile(event, fileType: string) {
    this.updateFileFormControl(event, fileType);
  }

  submitForm() {
    let formData: any = newFormData();
Object.keys(this.form.controls).forEach(formControlName => {
      formData.append(formControlName, this.form.get(formControlName).value);
    });

    this.http.post(' formData).subscribe(
            (response) =>console.log(response),
            (error) =>console.log(error)
        )
  }

  private updateFileFormControl(event: Event, formControlName: string) {
    const file = (event.target as HTMLInputElement).files[0];
    this.form.controls[formControlName].patchValue([file]);
    this.form.get(formControlName).updateValueAndValidity()
  }
}
  1. Multipart response

When Browser understand which enctype you use in your form for HTTP POST requests, user-agent configure list of name/value pairs to the server. Depending on the type and amount of data being transmitted, one of the methods will be more efficient than the other:

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

David Miller
Author

David Miller

David Miller brings 15 years of experience in global economics, personal finance strategy, and market dynamics. He specializes in turning complex economic trends into actionable insights for everyday readers.