直入正题,JS打开摄像头并截图上传至后端的一个完整步骤

1. 打开摄像头主要用到getUserMedia方法,然后将获取到的媒体流置入video标签

2. 截取图片主要用到canvas绘图,使用drawImage方法将video的内容绘至canvas中

3. 将截取的内容上传至服务器,将canvas中的内容转为base64格式上传,后端(PHP)通过file_put_contents将其转为图片

要注意的是,在chrome以外的浏览器中,使用摄像头或多或少会出现一些问题,可能也是老问题了,所以以下代码主要基于chrome使用

比如在最新版FireFox中的报错,不知为啥

1. 打开摄像头

getUserMedia 有新版本和旧版本两种,建议使用新版本

旧版本位于navigator 对象下,根据浏览器不同有所不同

// 获取媒体方法(旧方法)
navigator.getMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMeddia || navigator.msGetUserMedia;
if (navigator.getMedia) {
navigator.getMedia({
video: true
}, function(stream) {
mediaStreamTrack = stream.getTracks()[0]; video.src = (window.URL || window.webkitURL).createObjectURL(stream);
video.play();
}, function(err) {
console.log(err);
});
}

第一个参数中指示需要使用视频(video)或音频(audio),更多参见文档

第二个参数中指示调用成功后的回调,其中带一个参数(MediaStream),在旧版本中可以直接通过调用MediaStream.stop() 来关闭摄像头,不过在新版之中已废弃。需要使用MediaStream.getTracks()[index].stop() 来关闭相应的Track

第三个参数指示调用失败后的回调

新版本位于navigator.mediaDevices 对象下

if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
navigator.mediaDevices.getUserMedia({
video: true,
audio: true
}).then(function(stream) {
console.log(stream); mediaStreamTrack = typeof stream.stop === 'function' ? stream : stream.getTracks()[1]; video.src = (window.URL || window.webkitURL).createObjectURL(stream);
video.play();
}).catch(function(err) {
console.log(err);
})
}

与旧版类似,不过该方法返回了一个Promise对象,可以使用then和catch表示成功与失败的回调

更多参见文档

需要注意的是,MediaStream.getTracks() 返回的Tracks数组是按第一个参数倒序排列的

比如现在定义了

{
video: true,
audio: true
}

想关闭摄像头,就需要调用MediaStream.getTracks()[1].stop();

同理,0对应于audio的track

使用createObjectURL 将MediaStream写入video标签,就能够存储实时的媒体流数据(也可以方便的实时查看画面)

旧版本中webkitURL 对象以不被支持,需要使用URL对象

  <video width="200" height="150"></video>
<canvas width="200" height="150"></canvas> <p>
<button id="snap">截取图像</button>
<button id="close">关闭摄像头</button>
<button id="upload">上传图像</button>
</p> <img id="uploaded" width="200" height="150" />

2. 截取图像

将内容写入即可

// 截取图像
snap.addEventListener('click', function() {
context.drawImage(video, 0, 0, 200, 150);
}, false);

3. 关闭摄像头

// 关闭摄像头
close.addEventListener('click', function() {
mediaStreamTrack && mediaStreamTrack.stop();
}, false);

4. 上传截取的图像

canvas.toDataURL('image/png')

// 上传截取的图像
upload.addEventListener('click', function() {
jQuery.post('/uploadSnap.php', {
snapData: canvas.toDataURL('image/png')
}).done(function(rs) {
rs = JSON.parse(rs); console.log(rs); uploaded.src = rs.path;
}).fail(function(err) {
console.log(err);
});
}, false);

而这里的后端(PHP)则将获取的内容转换成图像文件保存

需要注意的是,要将base64的头部信息字段去掉再保存,否则似乎图像是损坏无法打开滴

<?php

    $snapData = $_POST['snapData'];
$snapData = str_replace('data:image/png;base64,', '', $snapData);
// $snapData = str_replace(' ', '+', $snapData); $img = base64_decode($snapData); $uploadDir = 'upload/';
$fileName = date('YmdHis', time()) . uniqid(); if (!(file_put_contents($uploadDir . $fileName, $img))) {
echo json_encode(array('code' => 500, 'msg' => '文件上传失败'));
} else {
echo json_encode(array('code' => 200, 'msg' => '文件上传成功', 'path' => $uploadDir . $fileName));
} ?>

完整JS代码

 <script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript">
function $(elem) {
return document.querySelector(elem);
} // 获取媒体方法(旧方法)
navigator.getMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMeddia || navigator.msGetUserMedia; var canvas = $('canvas'),
context = canvas.getContext('2d'),
video = $('video'),
snap = $('#snap'),
close = $('#close'),
upload = $('#upload'),
uploaded = $('#uploaded'),
mediaStreamTrack; // 获取媒体方法(新方法)
// 使用新方法打开摄像头
if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
navigator.mediaDevices.getUserMedia({
video: true,
audio: true
}).then(function(stream) {
console.log(stream); mediaStreamTrack = typeof stream.stop === 'function' ? stream : stream.getTracks()[1]; video.src = (window.URL || window.webkitURL).createObjectURL(stream);
video.play();
}).catch(function(err) {
console.log(err);
})
}
// 使用旧方法打开摄像头
else if (navigator.getMedia) {
navigator.getMedia({
video: true
}, function(stream) {
mediaStreamTrack = stream.getTracks()[0]; video.src = (window.URL || window.webkitURL).createObjectURL(stream);
video.play();
}, function(err) {
console.log(err);
});
} // 截取图像
snap.addEventListener('click', function() {
context.drawImage(video, 0, 0, 200, 150);
}, false); // 关闭摄像头
close.addEventListener('click', function() {
mediaStreamTrack && mediaStreamTrack.stop();
}, false); // 上传截取的图像
upload.addEventListener('click', function() {
jQuery.post('/uploadSnap.php', {
snapData: canvas.toDataURL('image/png')
}).done(function(rs) {
rs = JSON.parse(rs); console.log(rs); uploaded.src = rs.path;
}).fail(function(err) {
console.log(err);
});
}, false); </script>

JS打开摄像头并截图上传的更多相关文章

  1. 头像截图上传三种方式之一(一个简单易用的flash插件)(asp.net版本)

    flash中有版权声明,不适合商业开发.这是官网地址:http://www.hdfu.net/ 本文参考了http://blog.csdn.net/yafei450225664/article/det ...

  2. 使用Vlc.DotNet打开摄像头并截图 C#

      参考上一篇  使用vlc打开usb摄像头 理论上输入下面地址 "dshow:// :dshow-size=1600*1200:dshow-vdev=USB CAM2"C#就能打 ...

  3. Node + js实现大文件分片上传基本原理及实践(一)

    _ 阅读目录 一:什么是分片上传? 二:理解Blob对象中的slice方法对文件进行分割及其他知识点 三. 使用 spark-md5 生成 md5文件 四. 使用koa+js实现大文件分片上传实践 回 ...

  4. 通过修改ajaxFileUpload.js实现多图片动态上传并实现预览

    参考:http://smotive.iteye.com/blog/1903606 大部分我也是根据他的方法修改的,我也要根据name实现动态的多文件上传功能,但是有个问题使我一直无法实现多文件上传. ...

  5. Selenium常用API用法示例集----下拉框、文本域及富文本框、弹窗、JS、frame、文件上传和下载

    元素识别方法.一组元素定位.鼠标操作.多窗口处理.下拉框.文本域及富文本框.弹窗.JS.frame.文件上传和下载 元素识别方法: driver.find_element_by_id() driver ...

  6. 用js实现预览待上传的本地图片

    js实现预览待上传的本地图片,代码如下: <form name="form5" id="form5" method="post" ac ...

  7. php和js实现文件拖拽上传

    Dropzone.js实现文件拖拽上传 http://www.sucaihuo.com/php/1399.html demo http://www.sucaihuo.com/jquery/13/139 ...

  8. 在Asp.Net Core中配置使用MarkDown富文本编辑器实现图片上传和截图上传(开源代码.net core3.0)

    我们的富文本编辑器不能没有图片上传尤其是截图上传,下面我来教大家怎么实现MarkDown富文本编辑器截图上传和图片上传. 1.配置编辑器到html页 <div id="test-edi ...

  9. Js 之移动端图片上传插件mbUploadify

    一.下载 https://pan.baidu.com/s/1NEL4tkHoK4ydqdMi_hgWcw 提取码:vx7e 二.Demo示例 <div class="weui_uplo ...

随机推荐

  1. HTML编辑模式下制作表格

    前面有朋友问如何做图文并茂的音乐帖子,的确音乐能以表格式做出来,更能让人过目不忘,何况帖子制作过程本身就是创作,包含了制作人对音乐的理解和爱好.以下简单介绍用代码HTML制作表格,希望对大家有所帮助. ...

  2. javascript DOM 学习总结 (1)

    摘自javascript DOM编程艺术 1.首先介绍DOM的三个字母的含义: 1.1  D 如果没有document(文档),DOM 也无从谈起,当创建了一个网页并把他加载到web浏览器中时,DOM ...

  3. linux命令学习-1-less

    less 工具也是对文件或其它输出进行分页显示的工具,应该说是linux正统查看文件内容的工具,功能极其强大.less 的用法比起 more 更加的有弹性.在 more 的时候,我们并没有办法向前面翻 ...

  4. UVa 10360 - Rat Attack

    题目大意:有一个1025*1025的矩阵,每个矩阵元素保存这个点上老鼠的数量.现有一种气体炸弹,能覆盖“半径”为d的矩形,在这个范围内可以消灭所有的老鼠,让你找出合适的放置炸弹的位置使的消灭的老鼠数量 ...

  5. [osgEarth]osgEarth

    参考:http://bbs.osgchina.org/forum.php?mod=viewthread&tid=5484&extra=page%3D1&_dsign=70b15 ...

  6. javaEE开发中使用session同步和token机制来防止并发重复提交

    javaEE开发中使用session同步和token机制来防止并发重复提交 通常在普通的操作当中,我们不需要处理重复提交的,而且有很多方法来防止重复提交.比如在登陆过程中,通过使用redirect,可 ...

  7. spring异常处理

    http://cgs1999.iteye.com/blog/1547197 1 描述 在J2EE项目的开发中,不管是对底层的数据库操作过程,还是业务层的处理过程,还是控制层的处理过程,都不可避免会遇到 ...

  8. HDU2066:一个人的旅行(Dijkstra)

    Problem Description 虽然草儿是个路痴(就是在杭电待了一年多,居然还会在校园里迷路的人,汗~),但是草儿仍然很喜欢旅行,因为在旅途中 会遇见很多人(白马王子,^0^),很多事,还能丰 ...

  9. JavaScript 模拟策略模式

    /** * 模拟一个接口,其方法会抛出异常: */ function FlyInter () {} FlyInter.prototype.fly = function() { throw '实现这个接 ...

  10. SQL Server @@ERROR 用法

    @@error是系统函数,当没有发生错误时返回0,如果发生错误时@@error<>0,并返回错误号,每个SQL语句执行完,@@error值都会变. @@error只记录当前错误,如果存储过 ...