暑假在学校又开始繁忙的开发任务啦。这次遇到了文件上传,研究了一下步骤之后,我收获挺多的,所以就写一篇博客啦!
知识点- form表单
- HTTP 中MIME类型
- input 的file控件
- HTML5 FileApi
- 使用node.js 接收form data 类型
<!-- more --> form表单首先仔细探讨一下
form表单
,现在我们前后端的数据传递基本都是用Ajax
而不是直接使用form表单
,所以我们对于表单的认识非常的不足。一个表单里面有form元素,但
action
为空白的时候,刷新页面,会弹出一个警告框提示你已经填入表单,刷新数据将会丢失。
如果一个表单里面有一个type="submit"的button、或者type="submit"的input,或者type="image"的input,点击则会触发表单提交动作。即使你使用了return false,按钮也还是会提交submit动作。<button></button>的默认属性是submit,所以form内有没有设置type的button,也会触发submit()事件
form表单的属性
选择几个比较重要的属性说明 | 属性值 | 说明 |
---|---|---|
accept-charset | 服务器能够处理的字符集,多个字符集用空格分割 | |
action | 接受请求的URL,该值可以被form元素中的input或button元素的formaction属性覆盖 | |
enctype | 在发送到服务器之前应该如何对表单数据进行编码。 | |
method | 要发送的HTTP请求类型,通常是“get”或“post”,该值可以被form元素中的input或button元素的formmethod属性覆盖 | |
submit() | 提交表单 | |
target | 用于发送请求和接收响应的窗口名称,该值可以被form元素中的input或button元素的formtarget属性覆盖 |
enctype
有三个属性值application/x-www-form-urlencoded
这是默认值,在发送前,所有字符都会进行编码,空格转换为 "+" 加号,特殊符号转换为 ASCII HEX 值multipart/form-data
不对字符编码。
在使用包含文件上传控件的表单时,必须使用该值。text/plain
空格转换为 "+" 加号,但不对特殊字符编码。
target
属性规定在何处打开 action URL,有5个属性_blank
在新窗口中打开。_self
默认。在相同的框架中打开。_parent
在父框架集中打开。_top
在整个窗口中打开framename
在指定的框架中打开。
一般设置target为一个隐藏的iframe
,达到无刷新上传数据的效果
MIME类型是一种通知客户端其接收文件的多样性的机制:文件后缀名在网页上并没有明确的意义。因此,使服务器设置正确的传输类型非常重要,所以正确的MIME类型与每个文件一同传输给服务器。在网络资源进行连接时,浏览器经常使用MIME类型来决定执行何种默认行为。
MIME的组成结构非常简单;由类型与子类型两个字符串中间用“/”分隔而组成。并不允许空格存在。type 表示可以被分为复数子类的独立类型。subtype 表示细分后的每个类型。
type/subtype
简而言之就是MIME类型使得HTTP协议能够传输文件,MIME规定了用于表示各种各样的数据类型的符号化方法。 此外,在万维网中使用的HTTP协议中也使用了MIME的框架,标准被扩展为互联网媒体类型。
MIME与multipart/form-data的关系
Multipart types
表示细分领域的文件类型的种类,经常对应不同的 MIME类型。这是 复合文 件的一种表现方式。对于multipart/form-data
的例外部分,可以使用HTML Forms
和POST
方法来解决,以及使用状态码206 Partial Content 来发送整个文件的子集,而HTTP不能处理的复合文件使用一个特殊的方式:将信息直接传送给浏览器(这时可能会建立一个“另存为”窗口,但是却不知道如何去显示内联文件。
multipart/form-data
可用于HTML表单从浏览器发送信息给服务器。 作为多部分文档格式,它由边界线(一个由'--'开始的字符串)划分出的不同部分组成。每一部分有自己的实体,以及自己的 HTTP 请求头,Content-Disposition和 Content-Type 用于文件上传领域,最常用的 (Content-Length 因为边界线作为分隔符而被忽略)。
在这我们可以看到HTTP请求头中包含了Content-Type:multipart/form-data
,而boundary
则表示每个数据之间的分割线,方便服务器分割不同的数据。比如图中的name="file"
和name="flag"
一言以蔽之,MIME类型使得HTTP协议能够传输文件,multipart/form-data则使得form表单能够与服务器与客户端之间传递文件
标准写法<input type="file" name="file" multiple accept="image/gif,image/jpeg,image/jpg,image/png">
其中multiple
表示可选多个值。accept属性则表示能够通过文件上传提交的文件类型
出现一次input[type="file"]
则创建一个FileUpload
对象就会被创建。
该元素的 value
属性保存了用户指定的文件的名称,但是当包含一个 file-upload 元素的表单被提交的时候,浏览器会向服务器发送选中的文件的内容而不仅仅是发送文件名。
那如何获得文件的具体信息呢?
文件一开始其实 会被放到本地的一个临时文件夹内,然后我们可以使用一些方法来获得这个文件对象。
File对象的属性
- name : 文件名,不包含路径。
- type : 文件类型。图片类型的文件都会以 image/ 开头,可以由此来限制只允许上传图片。
- size : 文件大小。可以根据文件大小来进行其他操作。
- lastModified : 文件最后修改的时间。
<input type="file" id="files" multiple> <script> var elem = document.getElementById('files'); elem.onchange = function (event) { var files = event.target.files; for (var i = 0; i < files.length; i++) { // 文件类型为 image 并且文件大小小于 200kb if(files[i].type.indexOf('image/') !== -1 && files[i].size < 204800){ console.log(files[i].name); } } } </script>
FileReader对象
FileReader 对象允许Web应用程序异步读取存储在用户计算机上的文件(或原始数据缓冲区)的内容,使用 File 或 Blob 对象指定要读取的文件或数据。
其中File对象可以是来自用户在一个<input>
元素上选择文件后返回的FileList对象,也可以来自拖放操作生成的 DataTransfer对象,还可以是来自在一个HTMLCanvasElement
上执行mozGetAsFile()
方法后返回结果.
创建一个FileReader()对象
let reader = new FileReader();
该对象有以下方法:
-
abort:中断读取操作。
-
readAsArrayBuffer:读取文件内容到ArrayBuffer对象中。
-
readAsBinaryString:将文件读取为二进制数据。
-
readAsDataURL:将文件读取为data: URL格式的字符串。
- readAsText:将文件读取为文本。
最常见的应用就是上传图片的预览功能。
< input type="file" id="files" accept="image/jpeg,image/jpg,image/png">
< img src="blank.gif" id="preview">
<scrtpt>
var elem = document.getElementById('files'),
img = document.getElementById('preview');
elem.onchange = function () {
var files = elem.files,
reader = new FileReader();
if (files && files[0]) {
reader.onload = function (ev) {
img.src = ev.target.result;
}
reader.readAsDataURL(files[0]);
}
}
node.js接收formdata数据
formdata数据
和平常的数据并不一样,需要经过特殊的处理才能被后端正常接收。
这里我使用了 multiparty
这个包来处理
代码如下
var http = require('http');
var multiparty = require('multiparty');
http.createServer(function (req, res) {
var form = new multiparty.Form();
form.parse(req, function (err, fields, files) {
console.log(fields);
});
}).listen(3000);
参考链接