HTTP协议中,multipart/form-data格式用于向服务器发送二进制数据,通过这一内容类型(Content-Type)可以实现文件、图片的上传。由于这种格式发送的是二进制数据,在服务器端接收和处理数据时会与其它内容类型有所有区别。
HTTP协议中的文件上传
最早的HTTP协议中是不支持文件上传的,在1995年制定的rfc1867规范中,在HTTP POST请求的内容类型Content-Type中扩展了multipart/form-data类型,该类型用于向服务器发送二进制数据,以便支持文件的上传。
POST上传文件
我们通过form表单提交文件时,会构造类似像下面这样一个表单:
<form enctype="multipart/form-data" action="_URL_" method="POST"> <input name="userfile1" type="file"> <input type="submit" value="发送文件"> </form>
在使用form提交表单数据时,默认的编码格式为application/x-www-form-urlencoded,上传文件时需要通过enctype属性将编码方式设置为multipart/form-data。
HTTP数据提交与服务器数据解析
在包含请求体的请求中,提交的数据会按指定编码类型进行编码,而客户端会按编码方式设置请求头中的Content-Type字段。
在一个application/x-www-form-urlencoded编码的请求中,会设置一个如下的请求头:
Content-Type:application/x-www-form-urlencoded
而用于文件上传的编码方式multipart/form-data,会设置一个如下的请求头:
Content-type: multipart/form-data, boundary=AaB03x
服务器数据接收与解析
对于一个编码方式为application/x-www-form-urlencoded的请求来说,会对提交内容进行URL编码。服务器会收到类似如下内容:
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
请求头与请求体之间会有一个空行,服务器会对请求体以queryString的方式进行解码。
而对一个multipart/form-data的文件上传请求来说,收到的内容类似如下:
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 "color: #ff0000">Node.js中处理图片/文件上传
Node.js中处理文件上传的第三方模块,本站曾经介绍过使用formidable模块处理文件上传,下面简单介绍使用Node.js原生环境处理图片上传,上传文件时也可以参考处理。
首先,使用Node.js的HTTP模块创建一个HTTP服务器:
const http = require('http'); const fs = require('fs'); const util = require('util'); const querystring =require('querystring'); //用http模块创建一个http服务端 http.createServer(function(req, res) { if (req.url == '/upload' && req.method.toLowerCase() === 'get') { //显示一个用于文件上传的form res.writeHead(200, {'content-type': 'text/html'}); res.end( '<form action="/upload" enctype="multipart/form-data" method="post">'+ '<input type="file" name="upload" multiple="multiple" />'+ '<input type="submit" value="Upload" />'+ '</form>' ); } 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);在这一步中,我们创建HTTP 服务器,当GET请求时,会加载一上用于文件上传的form表单。上传文件会通过POST方式提交到服务器,这时服务端会通过parseFile函数解析并保存文件,其解析代码如下:
function parseFile (req, res) { req.setEncoding('binary'); var body = ''; // 文件数据 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); //获取文件二进制数据开始位置,即contentType的结尾 var upperBoundary = entireData.indexOf(contentType) + contentType.length; var shorterData = entireData.substring(upperBoundary); // 替换开始位置的空格 var binaryDataAlmost = shorterData.replace(/^\s\s*/, '').replace(/\s\s*$/, ''); // 去除数据末尾的额外数据,即: "--"+ boundary + "--" var binaryData = binaryDataAlmost.substring(0, binaryDataAlmost.indexOf('--'+boundary+'--')); // 保存文件 fs.writeFile(fileName, binaryData, 'binary', function(err) { res.end('图片上传完成'); }); } else { res.end('只能上传图片文件'); } }); }req是一个IncomingMessage对象,而该对象又实现了ReadableStream,所以我们可以用流的方式来接收数据。数据接收完成了,按rfc1867规范进行了数据处理,并通过fs模块保存了文件。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!
稳了!魔兽国服回归的3条重磅消息!官宣时间再确认!
昨天有一位朋友在大神群里分享,自己亚服账号被封号之后居然弹出了国服的封号信息对话框。
这里面让他访问的是一个国服的战网网址,com.cn和后面的zh都非常明白地表明这就是国服战网。
而他在复制这个网址并且进行登录之后,确实是网易的网址,也就是我们熟悉的停服之后国服发布的暴雪游戏产品运营到期开放退款的说明。这是一件比较奇怪的事情,因为以前都没有出现这样的情况,现在突然提示跳转到国服战网的网址,是不是说明了简体中文客户端已经开始进行更新了呢?
更新日志
- 凤飞飞《我们的主题曲》飞跃制作[正版原抓WAV+CUE]
- 刘嘉亮《亮情歌2》[WAV+CUE][1G]
- 红馆40·谭咏麟《歌者恋歌浓情30年演唱会》3CD[低速原抓WAV+CUE][1.8G]
- 刘纬武《睡眠宝宝竖琴童谣 吉卜力工作室 白噪音安抚》[320K/MP3][193.25MB]
- 【轻音乐】曼托凡尼乐团《精选辑》2CD.1998[FLAC+CUE整轨]
- 邝美云《心中有爱》1989年香港DMIJP版1MTO东芝首版[WAV+CUE]
- 群星《情叹-发烧女声DSD》天籁女声发烧碟[WAV+CUE]
- 刘纬武《睡眠宝宝竖琴童谣 吉卜力工作室 白噪音安抚》[FLAC/分轨][748.03MB]
- 理想混蛋《Origin Sessions》[320K/MP3][37.47MB]
- 公馆青少年《我其实一点都不酷》[320K/MP3][78.78MB]
- 群星《情叹-发烧男声DSD》最值得珍藏的完美男声[WAV+CUE]
- 群星《国韵飘香·贵妃醉酒HQCD黑胶王》2CD[WAV]
- 卫兰《DAUGHTER》【低速原抓WAV+CUE】
- 公馆青少年《我其实一点都不酷》[FLAC/分轨][398.22MB]
- ZWEI《迟暮的花 (Explicit)》[320K/MP3][57.16MB]