引子
<input> type
类型为 file 的 input 元素使得用户可以选择一个或多个元素以提交表单的方式上传到服务器上,或者通过 Javascript 的 File API 对文件进行操作 。
语法
属性 | 说明 |
---|---|
Value | DOMString 选择文件的路径 |
事件 | change 事件 input |
支持的常用属性 | accept, multiple, required |
IDL 属性 | 文件 和 值 |
方法 | select() |
-
解释
文件输入的 value 属性包括了一个 value 表示选择文件的路径DOMString。如果用户选择了多个文件,则该值表示他们选择的文件列表中的第一个文件。 可以使用输入的HTMLInputElement.files属性标识其他文件。 -
提示
- 如果选择了多个文件, 这个值表示第一个被选择的文件路径。JavaScript 可以通过 Input 的 FileList属性获取到其他的文件路径。
- 没有选择文件该值为空字符串。
- 为了阻止恶意软件猜测文件路径, 该值 以 C:\fakepath\为前缀。
使用
包括上面所说的 multiple 属性, 多个文件可以被同时选中. 只要用户所在的平台允许 (e.g. 摁住 Shift 或者 Control), 用户可以选择多个文件. 如果不希望多选, 忽略 multiple
属性.
在上面的例子中, 当表单被提交, 每个选中的文件名将被添加到 URL 参数中?file=file1.txt&file=file2.txt
获取选中文件信息
-
选中文件通过 HTMLInputElement.files 属性返回 — 返回值是一个 FileList 对象,这个对象是一个包含了许多 File 文件的列表(你也可以想列表一样操作它).
-
每个 File 对象包含了下列信息:
name: 文件名.
lastModified: UNIX timestamp 形式的最后修改时间.
lastModifiedDate: Date 形式的最后修改时间.
size: 文件的字节大小.
type: DOMString 文件的 MIME 类型.
限制允许的文件类型
accept 属性接受一个逗号分隔的 MIME 类型字符串, 如:
accept="image/png" or accept=".png"
— 只接受 png 图片.
accept="image/png, image/jpeg" or accept=".png, .jpg, .jpeg"
— PNG/JPEG 文件.
accept="image/*"
— 接受任何图片文件类型.
accept=".doc,.docx,.xml,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document"
— 接受任何 MS Doc 文件类型.
下面是一个更完整的例子:
示例代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>multiple file uploade</title>
</head>
<body>
<h4>多文件上传</h4>
<p>
使用 opacity 而不是 visibility: hidden / display: none的原因是因为visibility和display会让input不可选择
</p>
<form>
<div>
<label for="image_uploads">点击选择多图片上传 (PNG, JPG)</label>
<input type="file" id="image_uploads" name="image_uploads" accept=".jpg, .jpeg, .png" multiple>
</div>
<div class="preview">
<p>No files currently selected for upload</p>
</div>
<div>
<button>Submit</button>
</div>
</form>
<script>
// 获取 input 元素
var input = document.querySelector('input');
// 获取 preview 元素
var preview = document.querySelector('.preview');
// 将 input 变成透明的
input.style.opacity = 0;
// 监听 input 的 change 事件
input.addEventListener('change', updateImageDisplay);
// 监听函数
function updateImageDisplay() {
// while 循环清空 preview 中的内容.
while (preview.firstChild) {
preview.removeChild(preview.firstChild);
}
// 获取 FileList 对象并且将选中文件保存到 curFiles 变量中
var curFiles = input.files;
// 检查是否没有选中文件
if (curFiles.length === 0) {
var para = document.createElement('p');
para.textContent = 'No files currently selected for upload';
preview.appendChild(para);
} else {
// 创建有序列表
var list = document.createElement('ol');
preview.appendChild(list);
for (var i = 0; i < curFiles.length; i++) {
var listItem = document.createElement('li');
var para = document.createElement('p');
//检查文件类型是否正确
if (validFileType(curFiles[i])) {
// 在 div 中打印文件名称和 size
para.textContent = 'File name ' + curFiles[i].name + ', file size ' + returnFileSize(curFiles[i]
.size) + '.';
// 通过 window.URL.createObjectURL(curFiles[i]) 以及 css 产生预览图.
var image = document.createElement('img');
// 生成blob对象
image.src = window.URL.createObjectURL(curFiles[i]);
listItem.appendChild(image);
listItem.appendChild(para);
} else {
// 不正确则将结果告知用户
para.textContent = 'File name ' + curFiles[i].name +
': Not a valid file type. Update your selection.';
listItem.appendChild(para);
}
list.appendChild(listItem);
}
}
}
// 自定义的 validFileType() 接受一个 File 对象作为参数, 然后检查文件类型是否在 accept 列表中.
var fileTypes = [
'image/jpeg',
'image/pjpeg',
'image/png'
]
// 验证文件类型
function validFileType(file) {
for (var i = 0; i < fileTypes.length; i++) {
if (file.type === fileTypes[i]) {
return true;
}
}
return false;
}
// returnFileSize()方法接受一个数字作为参数以 KB/MB 的形式返回结果.
function returnFileSize(number) {
if (number < 1024) {
return number + 'bytes';
} else if (number > 1024 && number < 1048576) {
return (number / 1024).toFixed(1) + 'KB';
} else if (number > 1048576) {
return (number / 1048576).toFixed(1) + 'MB';
}
}
</script>
</body>
</html>