這期內(nèi)容當(dāng)中小編將會(huì)給大家?guī)?lái)有關(guān)Node.js 中怎么向HTTP服務(wù)器中上傳文件和圖片,文章內(nèi)容豐富且以專業(yè)的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。
成都創(chuàng)新互聯(lián)專注于信宜企業(yè)網(wǎng)站建設(shè),自適應(yīng)網(wǎng)站建設(shè),電子商務(wù)商城網(wǎng)站建設(shè)。信宜網(wǎng)站建設(shè)公司,為信宜等地區(qū)提供建站服務(wù)。全流程定制設(shè)計(jì),專業(yè)設(shè)計(jì),全程項(xiàng)目跟蹤,成都創(chuàng)新互聯(lián)專業(yè)和態(tài)度為您提供的服務(wù)HTTP協(xié)議中的文件上傳
最早的HTTP協(xié)議中是不支持文件上傳的,在1995年制定的rfc1867規(guī)范中,在HTTP POST請(qǐng)求的內(nèi)容類型Content-Type中擴(kuò)展了multipart/form-data類型,該類型用于向服務(wù)器發(fā)送二進(jìn)制數(shù)據(jù),以便支持文件的上傳。
POST上傳文件
我們通過(guò)form表單提交文件時(shí),會(huì)構(gòu)造類似像下面這樣一個(gè)表單:
在使用form提交表單數(shù)據(jù)時(shí),默認(rèn)的編碼格式為application/x-www-form-urlencoded,上傳文件時(shí)需要通過(guò)enctype屬性將編碼方式設(shè)置為multipart/form-data。
HTTP數(shù)據(jù)提交與服務(wù)器數(shù)據(jù)解析
在包含請(qǐng)求體的請(qǐng)求中,提交的數(shù)據(jù)會(huì)按指定編碼類型進(jìn)行編碼,而客戶端會(huì)按編碼方式設(shè)置請(qǐng)求頭中的Content-Type字段。
在一個(gè)application/x-www-form-urlencoded編碼的請(qǐng)求中,會(huì)設(shè)置一個(gè)如下的請(qǐng)求頭:
Content-Type:application/x-www-form-urlencoded
而用于文件上傳的編碼方式multipart/form-data,會(huì)設(shè)置一個(gè)如下的請(qǐng)求頭:
Content-type: multipart/form-data, boundary=AaB03x
服務(wù)器數(shù)據(jù)接收與解析
對(duì)于一個(gè)編碼方式為application/x-www-form-urlencoded的請(qǐng)求來(lái)說(shuō),會(huì)對(duì)提交內(nèi)容進(jìn)行URL編碼。服務(wù)器會(huì)收到類似如下內(nèi)容:
POST / HTTP/1.1 Content-Type: application/x-www-form-urlencoded Accept-Encoding: gzip, deflate Host: itbilu.com Content-Length: 23 Connection: Keep-Alive Cache-Control: max-age=0 key1=value1&key2=value2
請(qǐng)求頭與請(qǐng)求體之間會(huì)有一個(gè)空行,服務(wù)器會(huì)對(duì)請(qǐng)求體以queryString的方式進(jìn)行解碼。
而對(duì)一個(gè)multipart/form-data的文件上傳請(qǐng)求來(lái)說(shuō),收到的內(nèi)容類似如下:
POST / HTTP/1.1 Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryYN9YYwO9ESipYBIx Accept-Encoding: gzip, deflate Host: itbilu.com Content-Length: 22646 Connection: Keep-Alive Cache-Control: max-age=0 ------WebKitFormBoundaryoqBx9oYBhx4SF1YQ Content-Disposition: form-data; name="myName" itbilu.com ------WebKitFormBoundaryYN9YYwO9ESipYBIx Content-Disposition: form-data; name="upload"; filename="41GiLecHO3L.jpg" Content-Type: image/jpeg ????JFIF??C // 文件的二進(jìn)制數(shù)據(jù) …… --------WebKitFormBoundaryYN9YYwO9ESipYBIx--
在請(qǐng)求頭的Content-Type字段中,除了編碼類型為multipart/form-data描述外,還有一個(gè)boundary屬性,這是客戶端隨機(jī)生成的一個(gè)數(shù)據(jù)邊界描述。
如上所示,文件上傳時(shí)內(nèi)容是分段傳輸?shù)?,每一boundary表示一個(gè)fild(form表單控值)邊界。
如上面示例所示,上傳文件時(shí)除內(nèi)容描述外還包含一個(gè)的Content-Type文件MIME的描述,其后是一個(gè)空行和文件的二進(jìn)制數(shù)據(jù)。所有的表單數(shù)據(jù)結(jié)束后,會(huì)有一個(gè)”–”+boundary+”–”結(jié)束符。而服務(wù)器接收到數(shù)據(jù)后,同樣會(huì)根據(jù)boundary來(lái)進(jìn)行數(shù)據(jù)的接收和解析。
Node.js中處理圖片/文件上傳
Node.js中處理文件上傳的第三方模塊,本站曾經(jīng)介紹過(guò)使用formidable模塊處理文件上傳,下面簡(jiǎn)單介紹使用Node.js原生環(huán)境處理圖片上傳,上傳文件時(shí)也可以參考處理。
首先,使用Node.js的HTTP模塊創(chuàng)建一個(gè)HTTP服務(wù)器:
const http = require('http'); const fs = require('fs'); const util = require('util'); const querystring =require('querystring'); //用http模塊創(chuàng)建一個(gè)http服務(wù)端 http.createServer(function(req, res) { if (req.url == '/upload' && req.method.toLowerCase() === 'get') { //顯示一個(gè)用于文件上傳的form res.writeHead(200, {'content-type': 'text/html'}); res.end( '' ); } else if (req.url == '/upload' && req.method.toLowerCase() === 'post') { if(req.headers['content-type'].indexOf('multipart/form-data')!==-1) parseFile(req, res) } else { res.end('其它提交方式'); } }).listen(3000);
在這一步中,我們創(chuàng)建HTTP 服務(wù)器,當(dāng)GET請(qǐng)求時(shí),會(huì)加載一上用于文件上傳的form表單。上傳文件會(huì)通過(guò)POST方式提交到服務(wù)器,這時(shí)服務(wù)端會(huì)通過(guò)parseFile函數(shù)解析并保存文件,其解析代碼如下:
function parseFile (req, res) { req.setEncoding('binary'); var body = ''; // 文件數(shù)據(jù) var fileName = ''; // 文件名 // 邊界字符串 var boundary = req.headers['content-type'].split('; ')[1].replace('boundary=',''); req.on('data', function(chunk){ body += chunk; }); req.on('end', function() { var file = querystring.parse(body, '\r\n', ':') // 只處理圖片文件 if (file['Content-Type'].indexOf("image") !== -1) { //獲取文件名 var fileInfo = file['Content-Disposition'].split('; '); for (value in fileInfo){ if (fileInfo[value].indexOf("filename=") != -1){ fileName = fileInfo[value].substring(10, fileInfo[value].length-1); if (fileName.indexOf('\\') != -1){ fileName = fileName.substring(fileName.lastIndexOf('\\')+1); } console.log("文件名: " + fileName); } } // 獲取圖片類型(如:image/gif 或 image/png)) var entireData = body.toString(); var contentTypeRegex = /Content-Type: image\/.*/; contentType = file['Content-Type'].substring(1); //獲取文件二進(jìn)制數(shù)據(jù)開始位置,即contentType的結(jié)尾 var upperBoundary = entireData.indexOf(contentType) + contentType.length; var shorterData = entireData.substring(upperBoundary); // 替換開始位置的空格 var binaryDataAlmost = shorterData.replace(/^\s\s*/, '').replace(/\s\s*$/, ''); // 去除數(shù)據(jù)末尾的額外數(shù)據(jù),即: "--"+ boundary + "--" var binaryData = binaryDataAlmost.substring(0, binaryDataAlmost.indexOf('--'+boundary+'--')); // 保存文件 fs.writeFile(fileName, binaryData, 'binary', function(err) { res.end('圖片上傳完成'); }); } else { res.end('只能上傳圖片文件'); } }); }
req是一個(gè)IncomingMessage對(duì)象,而該對(duì)象又實(shí)現(xiàn)了ReadableStream,所以我們可以用流的方式來(lái)接收數(shù)據(jù)。數(shù)據(jù)接收完成了,按rfc1867規(guī)范進(jìn)行了數(shù)據(jù)處理,并通過(guò)fs模塊保存了文件。
上述就是小編為大家分享的Node.js 中怎么向HTTP服務(wù)器中上傳文件和圖片了,如果剛好有類似的疑惑,不妨參照上述分析進(jìn)行理解。如果想知道更多相關(guān)知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。