I encountered such a requirement in my work, and I needed to use nodejs to upload files. I used to only know how to upload files through the browser. If I use nodejs, it is equivalent to simulating the behavior of the browser. After Google, I realized that the browser simply uses the http protocol to transmit data to the server. The specific protocol is "RFC 1867 - Form-based File Upload in HTML". Uploading files through form forms on the browser is through this protocol. We can first see what data the browser sends to the server, and then we can implement the upload function according to the copy. When it comes to uploading files on form forms, everyone should be familiar with:
<form action="http://www.qq.com/" method="post"><input type="text" name="text1" /><br /><input type="text" name="text2" /><br /><input type="submit" /></form>
When submitting, you can see that the following data is sent to the server by using fiddler to capture the packet:
POST http://www.qq.com/ HTTP/1.1
Host: www.qq.com
Content-Length: 23
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
text1=hello&text2=world
It is worth noting that Content-Type defaults to application/x-www-form-urlencoded, so the message will be URL-encoded. For example, "Hello" will be encoded as %E4%BD%A0%E5%A5%BD.
Next, let’s take a look at how the form is uploaded. Everyone should be familiar with:
<form action="http://www.qq.com" method="post" enctype="multipart/form-data"><input type="file" name="myfile" /><input type="submit" value="submit" /></form>
Then create a new upload.txt text file with only the word hello world and upload it. We use fiddler to grab the package. We can find that sending past data is a little more complicated (a lot of other unrelated request lines have been removed, such as cache control and cookies):
POST http://www.qq.com/ HTTP/1.1
Host: www.qq.com
Content-Length: 199
Content-Type: multipart/form-data; boundary=---WebKitFormBoundarywr3X7sXBYQQ4ZF5G
-----WebKitFormBoundarywr3X7sXBYQQ4ZF5G
Content-Disposition: form-data; name="myfile"; filename="upload.txt"
Content-Type: text/plain
hello world
-----WebKitFormBoundarywr3X7sXBYQQ4ZF5G--
According to the definition of RFC 1867, we need to generate a piece of boundary data. This data cannot appear elsewhere in the content. This can be defined by yourself. The generation algorithm of each browser may be different. The above boundary is to separate data. After generating the separated data, the separated data can be placed in the Content-Type at the head and transmitted to the server, that is, the above Content-Type: multipart/form-data; boundary=---WebKitFormBoundarywr3X7sXBYQQ4ZF5G, In addition, the uploaded content needs to be separated into several segments with separate data, and each segment of data has the file name, and the name when uploading. The server uses this name to receive the file, and the file type Content-Type. In this example, text/plain. If the uploaded png image is image/png, it is image/png. After a blank line of the file type, the content of the uploaded file is also easy to understand. In this example, the uploaded text file is so the content can be displayed directly. If the uploaded image file is a binary file, the fiddler will display garbled code. After the content of the file ends, there is a blank line plus boundary data.
After understanding the details of the sending format, the next step is to use nodejs to program and implement it. Simply put, just send the data to the server according to the format.
const http = require('http');const fs = require('fs');//The post address is a php in the local service, used to test whether the upload is successful var options = {hostname: 'localhost',port: 80,path: '/get.php',method: 'POST'}//Generate separated data var boundaryKey = '---WebKitFormBoundaryjLVkbqXtIi0YGpaB'; //Read the file content that needs to be uploaded fs.readFile('./upload.txt', function (err, data) {//Stand out the separated data segment var payload = '--' + boundaryKey + '/r/n' + 'Content-Disposition:form-data; name="myfile"; filename="upload.txt"/r/n' + 'Content-Type:text/plain/r/n/r/n';payload += data;payload += '/r/n--' + boundaryKey + '--';//Send a request var req = http.request(options, function (res) {res.setEncoding('utf8');res.on('data', function (chunk) {console.log('body:' + chunk);});});req.on('error', function(e) {console.error("error:"+e);});//Write boundary, the size of the data to be sent, and the data itself into the request req.setHeader('Content-Type', 'multipart/form-data; boundary='+boundaryKey+'');req.setHeader('Content-Length', Buffer.byteLength(payload, 'utf8'));req.write(payload);req.end();});The focus of this article is to understand the protocol and implement it with code. There are still many optimizations in code organization.
Finally, in the local apache, simply write a php to save the uploaded file to use as a test:
<?php$filePath = './upload.txt';move_uploaded_file($_FILES['myfile']['tmp_name'] , $filePath);echo "ok";?>
In addition, according to RFC 1867, the function of uploading multiple files at once can be realized. This will not be described in detail here. If necessary, refer to RFC 1867 for detailed implementation.
The above is the Node.js file upload introduced by the editor. I hope it will be helpful to everyone. If you have any questions, please leave me a message and the editor will reply to everyone in time. Thank you very much for your support to Wulin.com website!