Recently, WHEN I was dealing with a node file upload problem, I encountered a great obstacle. Finally, I checked a lot of information and asked the big guy to solve it. This prompted me to make this part completely clear, the next time I encounter can not look up information everywhere to solve the problem

Content-type Basic concept

Content-type is the HTTP entity header that indicates the MIME Type of the resource. It can appear in either the request header or the response header.

  1. In the request header, the client tells the server what type of data to send, so that the server knows how to properly process the data.
  2. In the response header, the server tells the client the type of the response data to be returned, and the client (browser) processes it based on the MIME type, or the developer processes it himself.

Content-type is written in a format similar to the following

Content-Type: text/html; charset=utf-8
Content-Type: multipart/form-data; boundary=something
Copy the code

The value part consists of three main parts

  1. Mimetype (MIME type of resource or data)
  2. Charset (character set)
  3. Boundary (content boundary, useful for multiple types of content)

Between parts; Segmentation, which MIME types are many, the following mainly said that we commonly used several

Content-Length

The most common one with content-type is content-length

Content-length specifies the Length of eight bytes. If content-length is present and valid, the value must be correct, otherwise unexpected errors will occur.

  1. Content-length larger than the actual Length may result in no response (the client or server waits for the next byte to be read and fails to read it)
  2. Content-length may truncate data if it is smaller than the actual Length

Content-type is applied to the response

Common content-types in responses are:

  1. application/jsonAjax request data returns JSON
  2. application/javascriptJavascript files
  3. text/cssCSS file (note that unlike JS, this is text, application usually represents executable or parsed binary data)
  4. text/htmlThe HTML file
  5. text/plainPlain text

Content-type is applied to the request

Requests to send data use POST requests, such as those sent to a form, and the content-Type is usually used

application/x-www-form-urlencoded

Application/X-www-form-urlencoded data will be coded. For non-alphanumeric characters, percent-encoding is performed. Special characters are expressed in ASCII hexadecimal format followed by %, and whitespace is expressed as + or %20

POST / HTTP / 1.1
Host: test.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 19

name=xiaoming&age=8
Copy the code

application/json

Application/JSON is also used a lot now in request headers, where the high-speed server sends a JSON string

POST / HTTP / 1.1
Host: test.com
Content-Type: application/json
Content-Length: 22

{"name": "xiaoming"."age": 8}
Copy the code

multipart/form-data

Multipart /form-data is usually used when the form needs to be passed to the file, because the file needs to be represented in binary mode

POST/test. HTTP / 1.1 HTMLHost: test.com 
Content-Type: multipart/form-data; boundary="boundary" --boundaryContent-Disposition: form-data; name="name1" 

value1 
--boundary 
Content-Disposition: form-data; name="name2"

value2
Copy the code

File upload

Upload in browser

File uploads in the browser require the construction of a FormData object, and the data is added to the FormData object using append. The File is usually of type File or BLOB. Once the FormData is constructed, pass it in via the request API, and the content-Type and Content-Length browser client will set it automatically

const file = new File(["foo"]."foo.txt", {
  type: "text/plain",})const form = new FormData()
form.append('name'.'xiaoming')
form.append('file', file, 'text.png')
form.append('age'.8)

const xhr = new XMLHttpRequest()
xhr.open('POST'.'http://test.com/test/upload')
xhr.send(form)
Copy the code

The request reads like this

POST HTTP / 1.1 / test/uploadHost: test.com 
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryYr963ldXs1XPBv7A

------WebKitFormBoundaryYr963ldXs1XPBv7A
Content-Disposition: form-data; name="name"

xiaoming
------WebKitFormBoundaryYr963ldXs1XPBv7A
Content-Disposition: form-data; name="file"; filename="text.png"
Content-Type: text/plain

foo
------WebKitFormBoundaryYr963ldXs1XPBv7A
Content-Disposition: form-data; name="age"

8
------WebKitFormBoundaryYr963ldXs1XPBv7A--
Copy the code

The Node in the upload

So what do you do if you want to upload like a browser in Node? Node does not have FormData objects, so we can use the third-party form-data package

const FormData = require('form-data')
const fs = require('fs')
 
const mime = 'image/png'
const form = new FormData()
form.append('name'.'xiaoming')
form.append('file', fs.createReadStream('/foo/bar.png'), {
	contentType: mime,
    filename: 'test.png'
})
form.append('age'.8)

// Get the content length
const length = await new Promise((resolve, reject) = > {
    data.getLength((err, length) = > {
        if (err) {
            reject(err)
        } else {
            resolve(length)
        }
    })
})

// Here we use axios to send the request, which would be the same in any library. The main thing is to set 'content-type' and 'content-Length' correctly
const headers = data.getHeaders()
const res = await axios
  .post(pssConfig.uploadLink, data, {
      responseType: 'json'.headers: {
          'Content-Type': headers['content-type'].'Content-Length': length
      }
  })   
Copy the code

conclusion

Thank you for your patience. I hope I can correct a lot of bad things. Often we ignore the seemingly simple things, but the importance of these basics is revealed when we actually use them. But the most important, whether it is to check information or ask others, after solving the problem should be timely thinking and summary to become their own things

Thank you for your support

Posts will sync with Github and Blog

And recently opened a new public account, will continue to share their own ideas, keep updated, hope to have more exchanges with you ~