Multipart/form-data 示例

我想知道是否有人能与我分享一个包含以下内容的多部分/表单数据示例:

  1. 一些形状参数
  2. 很多文件
406723 次浏览

编辑 : 我保留了一个类似的,但更深入的答案: < a href = “ https://stackoverflow. com/a/28380690/895245”> https://stackoverflow.com/a/28380690/895245

要确切了解正在发生的情况,可以使用 nc -l或 ECHO 服务器和用户代理(如浏览器或 cURL)。

将表单保存为 .html文件:

<form action="http://localhost:8000" 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>

创建要上传的文件:

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

跑步:

nc -l localhost 8000

在浏览器上打开 HTML,选择文件,点击提交并检查终端。

nc打印收到的请求,Firefox 发送:

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--

或者,cURL 应该发送与您的浏览器表单相同的 POST 请求:

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

您可以使用以下命令进行多项测试:

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

非常感谢西罗 · 桑蒂利的回答!我发现他对边界的选择是相当“不愉快”的,因为所有这些连字符: 事实上,正如@Fake Name 评论的那样,当你在请求中使用边界时,前面会多出两个连字符:

例如:

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--

我发现 在这个 w3.org 页面上可以在多部分/表单数据中封装多部分/混合头,只需在多部分/混合数据中选择另一个边界字符串,并使用该字符串封装数据。最后,您必须“关闭”FILO 中使用的所有边界,以关闭 POST 请求(比如:

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--

看看上面的链接。

这里有一个多部分数据(角度)的例子:

  1. Trip-upload.html
<form [formGroup]="form" enctype="multipart/form-data" (ngSubmit)="submitForm()">
<div class="form-group">
<label for="trip">Trip:</label>
<input formControlName="name"  type="text" id="trip" name="trip" placeholder="Name of the trip">
</div>


<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('http://localhost:4200/api/trip', 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. 多部分响应

当浏览器了解您在表单中为 HTTP POST 请求使用的是哪种类型时,将向服务器提供名称/值对的用户代理配置列表。根据所传输数据的类型和数量,其中一种方法将比另一种方法更有效: enter image description here

enter image description here