In the work encountered such a demand, need to use Nodejs to upload files, before just know how to upload files through the browser, with nodejs words, the equivalent of simulated browser behavior. After Google, understand that the browser is nothing more than using the HTTP protocol to transfer data to the server, the specific protocol is "RFC 1867-form-based file Upload in HTML", in the browser through the form form to upload files through this Protocol , we can first look at the browser to the server to send what data, you can according to the gourd painting scoop upload function realized. Speaking of form form upload file, you should be very familiar with:
<formAction= "http://www.qq.com/"Method= "POST"> <inputtype= "text"name= "Text1" /><BR/> <inputtype= "text"name= "Text2" /><BR/> <inputtype= "Submit" /></form>
At the time of submission, you can see the data sent to the server using the Fiddler grab packet:
POST http://www.qq.com/HTTP/1.1Host:www.qq.comContent-Length:23Content-Type:application/x-www-form-urlencoded; Charset=utf-8text1=hello&text2=world
It is important to note that Content-type defaults to application/x-www-form-urlencoded, so messages are URL encoded. For example, "Hello" will be encoded as%E4%BD%A0%E5%A5%BD.
Next, let's look at how the form form is uploaded. We should not be strangers either:
<formAction= "Http://www.qq.com"Method= "POST"enctype= "Multipart/form-data"> <inputtype= "File"name= "MyFile" /> <inputtype= "Submit"value= "Submit" /></form>
Then create a new upload.txt text file with the word "Hello World", and we'll eat it with fiddler to catch the packet, and we can find that sending the past data is a little more complicated (we've got rid of a lot of other okay requests. such as cache control and cookies):
POST Http://www.qq.com/HTTP/1.1Host:www.qq.comContent-Length:199Content-Type:multipart/form-data; boundary=----webkitformboundarywr3x7sxbyqq4zf5g------webkitformboundarywr3x7sxbyqq4zf5gcontent-disposition: Form-data; Name= "MyFile"; Filename= "Upload.txt" Content-type:text/plainhello World------webkitformboundarywr3x7sxbyqq4zf5g--
According to the definition of RFC 1867, we need to generate a piece of boundary data, this data can not appear elsewhere in the content, this may be defined by itself, in each browser generation algorithm may be different, the above boundary is the separation of data, generated by separating the data, You can put the separation data in the head of the Content-type inside the service side, that is, the above content-type:multipart/form-data; boundary=----webkitformboundarywr3x7sxbyqq4zf5g, in addition, the content of the upload, you need to separate the data into a number of segments, and then each piece of data inside the file name, as well as the name of the upload time, The server is to use this name to receive files, as well as the type of file Content-type, in this case is text/plain, if the upload is a PNG image is image/png. File type of a blank line is the content of the uploaded file, in this case is also for easy to understand the upload is a text file so the content directly can be displayed, if the upload is a picture file, because it is a binary file, Fiddler is garbled. After the content of the file is finished, it is a blank line plus the boundary data.
After understanding the details of the send format, the next step is to use Nodejs to program the implementation, simply speaking, is to format the data sent to the server on the line.
Const HTTP = require (' http '); Const FS= Require (' FS ');//The post address is a PHP for local service to test whether the upload was successfulvarOptions ={hostname:' localhost ', Port:80, Path:'/get.php ', Method:' POST '}//Generate delimited DatavarBoundarykey = '----webkitformboundaryjlvkbqxtii0ygpab '; //read the contents of the file to be uploadedFs.readfile ('./upload.txt ',function(err, data) {//Assemble delimited data segments varPayload = '--' + 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 Request varreq = 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 the boundary, the size of the data to be sent, and the data itself into the requestReq.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 in code, where there are many optimizations to the code organization.
At the end of the local Apache, simply write a PHP to save the uploaded file for use as a test:
<? PHP $filePath = './upload.txt '; Move_uploaded_file ($_files$filePath); Echo "OK";? >
In addition, according to RFC 1867 can also achieve the ability to upload multiple files at once, this is not detailed here, you can refer to the RFC 1867来 implementation.
node. js Uploading Files