写在前面:
这里先来介绍下input:file的几个属性:
accept:规定通过文件上传来提交的文件的类型。
capture:该属性用于调用设备的摄像头或麦克风。
multiple:可勾选多文件,调用系统摄像头或者录音机都只是单文件。
一、常规上传demo(选取本地的图片/视频文件进行上传)
移动端查看 演示案例
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<title>图片/视频上传&&预览</title>
<style>
*{
margin:0;
padding:0;
}
html{
font-size: 10px;
}
ul,ol{
list-style-type:none;
}
.clearfix:after,.clearfix:before{
display:table;
content:' ';
}
.clearfix:after{
clear:both
}
.tc{
text-align:center;
line-height: 3.5rem;
font-size: 2rem;
color: #71777D;
}
.select,.select_video{
height:3rem;
line-height:3rem;
border:1px solid #f20d0d;
margin:0.5rem 1rem;
position:relative;
background: rgba(242,13,13,.06);
color: #f20d0d;
}
.select label,.select_video label{
width:100%;
position:absolute;
top:0;
left:0;
font-size:14px;
color:#333;
font-size: 1.6rem;
}
#upload,#upload_video{
display:none;
}
.preview,.video_preview{
margin:0.5rem 1rem;
border:1px solid #f1f1f1;
padding:4px;
min-height: 7.5rem;
display:none;
}
.video_preview video{
width:100%;
height:16rem;
object-fit:fill;
}
.preview_img_list li{
float:left;
width:25%;
padding:2px 0;
}
.preview_img_list li img{
vertical-align:top;
max-width:98%;
}
.btn{
background: #f20d0d;
color:#fff;
height:3rem;
font-size: 1.7rem;
line-height:3rem;
margin:2rem 1rem;
border-radius:0.5rem;
box-shadow: 0 8px 16px 0 rgba(242,13,13,.2);
}
</style>
</head>
<body>
<h2 class="tc">图片上传及预览</h2>
<form action="">
<div class="select tc">
<label for="upload">图片上传及预览</label>
<input type="file" id="upload" accept="image/*">
</div>
<div class="preview">
<ul class="preview_img_list clearfix">
</ul>
</div>
<div class="select_video tc">
<label for="upload_video">视频上传及预览</label>
<input type="file" id="upload_video" accept="video/*">
</div>
<div class="video_preview">
</div>
<div class="submit btn tc">上传</div>
</form>
</body>
<script>
window.onload = function() {
var uploadBtn = document.querySelector('#upload');
var previewImgList = document.querySelector('.preview_img_list');
var uploadVideo = document.querySelector('#upload_video');
var submitBtn = document.querySelector('.submit');
imgArr = new Array();
uploadBtn.addEventListener('change', function() {
var imgLen = this.files.length;
var liLen = previewImgList.getElementsByTagName('li').length;
var ImgLen = imgLen + liLen;
if (ImgLen > 8) {
alert("上传最大数量不能大于8");
return false;
}
document.querySelector(".preview").style.display = 'block';
for (var i = 0; i < imgLen; i++) {
var file = this.files[i];
var imgType = /^image\//;
if (!imgType.test(file.type)) {
continue;
}
var li = document.createElement('li');
var img = document.createElement("img");
li.appendChild(img);
previewImgList.appendChild(li);
var reader = new FileReader();
reader.onload = (function(aImg) {
return function(e) {
aImg.src = e.target.result;
initHW();
imgArr.push(e.target.result);
};
})(img);
reader.readAsDataURL(file);
}
}, false);
uploadVideo.addEventListener('change', function() {
var file = this.files[0];
var videoType = /^video\//;
if (!videoType.test(file.type)) {
alert("所选文件不是合法的视频文件");
return false;
}
var pv = document.querySelector('.video_preview');
var video = document.createElement('video');
video.setAttribute('controls', 'controls');
video.style.width = "100%";
pv.appendChild(video);
pv.style.display = "block";
var reader = new FileReader();
reader.onload = (function(aImg) {
return function(e) {
aImg.src = e.target.result;
};
})(video);
reader.readAsDataURL(file);
video.play();
}, false);
submitBtn.addEventListener('click', function() {
if (!imgArr.length) {
alert('请选择要上传的图片');
return false;
}
var form = document.querySelector('form');
var fd = new FormData(form);
for (var i = 0; i < imgArr.length; i++) {
fd.append('file[]', imgArr[i]);
}
// 这里写上传服务器,fd为上传参数
}, false);
}
function initHW() {
var previewImgList = document.querySelector('.preview_img_list');
var Lis = previewImgList.getElementsByTagName('li');
var LisLen = Lis.length;
if (LisLen > 1) {
var img = Lis[0].getElementsByTagName('img')[0];
var imgW = img.width;
var imgH = img.height;
for (var i = 1; i < LisLen; i++) {
var img = Lis[i].getElementsByTagName('img')[0];
img.style.width = imgW + 'px';
img.style.height = imgH + 'px';
}
}
}
</script>
</html>
二、调摄像头拍照/录像上传
这里就要使用到input:file, 指定capture属性调用默认相机,摄像,录音功能。
当accept=”audio/或video/”时capture只有两种值,一种是user,用于调用面向人脸的摄像头(例如手机前置摄像头),一种是environment,用于调用环境摄像头(例如手机后置摄像头)。官方文档
capture的值网上流传的比如:camera–照相机;camcorder–摄像机;microphone–录音;filesystem–文件系统,这些这里统称为‘其他值’。
对capture各种取值,以及是否有multiple属性探究可以使用移动端查看 演示案例
使用总结:
iOS最遵守遵守HTML5规范,其次是X5内核,安卓的webview基本忽略了capture。
理想情况下应该按照如下开发webview:
- 当accept=”image/*”时,capture=”user”调用前置照相机,capture=”其他值”,调用后置照相机
- 当accept=”video/*”时,capture=”user”调用前置录像机,capture=”其他值”,调用后置录像机
- 当accept=”image/,video/”,capture=”user”调用前置摄像头,capture=”其他值”,调用后置摄像头,默认照相,可切换录像
- 当accept=”audio/*”时,capture=”放空或者任意值”,调用录音机
- 当input没有capture时,根据accppt类型给出文件夹选项以及摄像头或者录音机选项
- input含有multiple时访问文件夹可勾选多文件,调用系统摄像头或者录音机都只是单文件
- 无multiple时都只能单文件