Form

GitbookFrontend2021-01-22


📑 content-type


Form handling process

post 请求 content-type,即数据请求的格式主要设置方式:

  • application/x-www-form-urlencoded(大多数请求可用:eg:‘name=Denzel&age=18’)
  • multipart/form-data(文件上传,这次重点说)
  • application/json(json 格式对象,eg:{‘name’:‘Denzel’,‘age’:‘18’})
  • text/xml(现在用的很少了,发送 xml 格式文件或流,webservice 请求用的较多)

📑 post 请求 Content-type 到底该不该设置


我得出的结论是,要正确设置。fetch 发送post字符类请求时,

  • 非文件上传时,无关你发送的数据格式是 application/x-www-form-urlencoded 或者 application/json 格式数据, 你不设置请求头,fetch 会给你默认加上一个 Content-type = text/xml 类型的请求头,有些第三方 JAX 可以自己识别发送的数据,并自己转换, 但fetch绝对不会;
  • 文件上传请求时,因为不知道那个 boundary 的定义方式,所以就如建议的一样,我们不设置Content-type

📑 问题症结原文


文件上传时,You should never set that header yourself. We set the header properly with the boundary. If you set that header, we won’t and your server won’t know what boundary to expect (since it is added to the header). Remove your custom Content-Type header and you’ll be fine.

简言之,就是文件上传时,headers 里不要加:content-type:multipart/form-data

let data = new FormData();
data.append("file", $("#realFile").files[0]);
data.append("name", "denzel"), data.append("flag", "test");
const option = {
	method: "post",
	mode: "cors",
	headers: {
		// 'Content-Type': 'multipart/form-data'
	},
	body: data,
};
fetch("http://localhost:8089/Analyse/imgUploadServlet", option)
	.then(function (response) {
		if (response.ok) {
			console.log("suc");
			return response.text();
		} else {
			console.log("网络错误,请稍后再试");
			return;
		}
	})
	.then(function (data) {
		console.log("imgUrl", data);
	});

FormData, Form submit


  1. form submit with “Content-Type=application/json”

    fetch("/api/account/signup", {
    	method: "POST",
    	headers: {
    		"Content-Type": "application/json",
    	},
    	body: JSON.stringify(this.state),
    });

    Server-side uses body-parser to parse:

    // parse application/json
    app.use(bodyParser.json());
  2. formData (file upload)

    fetch("/api/account/signup", {
    	method: "POST",
    	body: data,
    });

    Server-side uses parseFormdata to parse FormData.

    Default: Content-Type: multipart/form-data

    router.post("/signup", (req, res, next) => {
    	// this is the solution for 'formData'.
    	parseFormdata(req, (err, data) => {
    		console.log("formData, multipart/form-data: ", data.fields, data.parts);
    	});
    });