blob和base64实现文件上传
日期:2020-06-19
来源:程序思维浏览:1849次
有时候,我们不想通过上传本地图片的方式上传图片,而是通过相机拍照,将这个拍照后的图片直接上传到服务器上,不需要保存到本地。
比如,用video模拟一个摄像头,通过webrtc调用摄像头的方式拍一张照,然后通过canvas通过getContext('2d')获取的绘图对象CanvasRenderingContext2D的drawImage(video, x, y, width, heigth)方法将video图像通过canvas直接画到html页面上,用来呈现拍照后的结果。
通常的做法是用
<input type="file"/>
的方式上传图片的。但这种方式是要求图片具体存在的,本地或者url路径上的。
现在我们来通过canvas的toDataURL或者toBlob方法、File对象、FormData对象来通过ajax上传图片。
<video id="video"></video>
<canvas id="canvas"></canvas>
<script type="text/javascript">
// 调用摄像头的代码省略...
let video = document.querySelector('#video')
let canvas = document.querySelector('#canvas')
let context = canvas.getContext('2d')
context.drawImage(video, 0, 0, 300, 150) // 将video标签的图片画到canvas上
// 正片开始
// 通过canvas调用toBlob方法获取blob对象,传入一个回调函数,这个回调函数的参数就是blob对象
let s = canvas.toBlob(function (blob) {
/*
* 注意第一个File的构造方法第一个参数必须要用[]包起来,表明这是一个数组
* 第二个参数是这个文件名
* 第三个参数是选项,其中通过type指定这个文件的mime值
*/
let file2 = new File([blob], 'a.jpg', {type: 'image/jpg'})
// ajax上传文件不能像上传普通对象那样,得用上FormData
let formData = new FormData()
formData.append('file', file2)
$.ajax({
url: '/a', // 后台接口
type: 'POST',
processData: false, // processData和contentType必须指定为false
contentType: false,
cache: false,
data: formData,
success(res) {
console.log("上传完成!")
}
})
});
</script>
第二种方式,通过base64转码,这里只看js代码
这是canvas调用toDataURL方法将图片base64编码
var Img = new Image(),
dataURL='';
Img.src=url;
Img.onload=function(){ //要先确保图片完整获取到,这是个异步事件
var canvas = document.createElement("canvas"), //创建canvas元素
width=Img.width, //确保canvas的尺寸和图片一样
height=Img.height;
canvas.width=width;
canvas.height=height;
canvas.getContext("2d").drawImage(Img,0,0,width,height); //将图片绘制到canvas中
let base64 = canvas.toDataURL(); // 同样通过canvas的toDataURL方法将canvas图片Base64编码
let bstr = atob(base64.split(',')[1]); // atob是将base64编码解码,去掉data:image/png;base64,部分
let n = bstr.length;
let u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
// 写法同上
let file2 = new File([u8arr], 'a.jpg', {type: 'image/jpg'})
let formData = new FormData()
formData.append('file', file2)
console.log(formData)
$.ajax({
url: '/a',
type: 'POST',
processData: false,
contentType: false,
cache: false,
data: formData,
success(res) {
console.log("上传完成!")
}
})
};
php上传文件代码:
<?php
/*
接收方法:$_POST[""],$_GET[""],$_REQUEST[""]
$_FILES:把整个文件读入一个数组中
*/
//print_r($_FILES);
/*echo "上传文件名称是:".$_FILES["myfile"]["name"]."<br>";
echo "上传文件类型是:".$_FILES["myfile"]["type"]."<br>";
echo "上传临时文件是:".$_FILES["myfile"]["tmp_name"]."<br>";*/
$copyto="uploadfiles/".time().$_FILES["myfile"]["name"];
$filesize=$_FILES["myfile"]["size"]/1024;
if ($_FILES["myfile"]["error"]>0){
switch($_FILES["myfile"]["error"]){
case 1:
echo "<script>alert ('上传文件超过了php.ini中upload_max_filesize这个选项设置的值');history.go(-1)</script>";
break;
case 2:
echo "<script>alert ('上传的文件大小超过了HTML表单中MAX_FILE_SIZE选项指定的值');history.go(-1)</script>";
break;
case 3:
echo "<script>alert ('文件只有被部分上传');history.go(-1)</script>";
break;
case 4:
echo "<script>alert ('没有文件上传');history.go(-1)</script>";
break;
}
exit;
}else{
if(is_uploaded_file($_FILES["myfile"]["tmp_name"])){
if($filesize<1024){
if(move_uploaded_file($_FILES["myfile"]["tmp_name"],$copyto)){
echo "上传文件成功;上传文件大小为".$_FILES["myfile"]["size"]/1024 ."kb";
}else{
echo "上传文件失败";
}
}else{
echo "文件大小超过了限制";
}
}
}
?>
比如,用video模拟一个摄像头,通过webrtc调用摄像头的方式拍一张照,然后通过canvas通过getContext('2d')获取的绘图对象CanvasRenderingContext2D的drawImage(video, x, y, width, heigth)方法将video图像通过canvas直接画到html页面上,用来呈现拍照后的结果。
通常的做法是用
<input type="file"/>
的方式上传图片的。但这种方式是要求图片具体存在的,本地或者url路径上的。
现在我们来通过canvas的toDataURL或者toBlob方法、File对象、FormData对象来通过ajax上传图片。
<video id="video"></video>
<canvas id="canvas"></canvas>
<script type="text/javascript">
// 调用摄像头的代码省略...
let video = document.querySelector('#video')
let canvas = document.querySelector('#canvas')
let context = canvas.getContext('2d')
context.drawImage(video, 0, 0, 300, 150) // 将video标签的图片画到canvas上
// 正片开始
// 通过canvas调用toBlob方法获取blob对象,传入一个回调函数,这个回调函数的参数就是blob对象
let s = canvas.toBlob(function (blob) {
/*
* 注意第一个File的构造方法第一个参数必须要用[]包起来,表明这是一个数组
* 第二个参数是这个文件名
* 第三个参数是选项,其中通过type指定这个文件的mime值
*/
let file2 = new File([blob], 'a.jpg', {type: 'image/jpg'})
// ajax上传文件不能像上传普通对象那样,得用上FormData
let formData = new FormData()
formData.append('file', file2)
$.ajax({
url: '/a', // 后台接口
type: 'POST',
processData: false, // processData和contentType必须指定为false
contentType: false,
cache: false,
data: formData,
success(res) {
console.log("上传完成!")
}
})
});
</script>
第二种方式,通过base64转码,这里只看js代码
这是canvas调用toDataURL方法将图片base64编码
var Img = new Image(),
dataURL='';
Img.src=url;
Img.onload=function(){ //要先确保图片完整获取到,这是个异步事件
var canvas = document.createElement("canvas"), //创建canvas元素
width=Img.width, //确保canvas的尺寸和图片一样
height=Img.height;
canvas.width=width;
canvas.height=height;
canvas.getContext("2d").drawImage(Img,0,0,width,height); //将图片绘制到canvas中
let base64 = canvas.toDataURL(); // 同样通过canvas的toDataURL方法将canvas图片Base64编码
let bstr = atob(base64.split(',')[1]); // atob是将base64编码解码,去掉data:image/png;base64,部分
let n = bstr.length;
let u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
// 写法同上
let file2 = new File([u8arr], 'a.jpg', {type: 'image/jpg'})
let formData = new FormData()
formData.append('file', file2)
console.log(formData)
$.ajax({
url: '/a',
type: 'POST',
processData: false,
contentType: false,
cache: false,
data: formData,
success(res) {
console.log("上传完成!")
}
})
};
php上传文件代码:
<?php
/*
接收方法:$_POST[""],$_GET[""],$_REQUEST[""]
$_FILES:把整个文件读入一个数组中
*/
//print_r($_FILES);
/*echo "上传文件名称是:".$_FILES["myfile"]["name"]."<br>";
echo "上传文件类型是:".$_FILES["myfile"]["type"]."<br>";
echo "上传临时文件是:".$_FILES["myfile"]["tmp_name"]."<br>";*/
$copyto="uploadfiles/".time().$_FILES["myfile"]["name"];
$filesize=$_FILES["myfile"]["size"]/1024;
if ($_FILES["myfile"]["error"]>0){
switch($_FILES["myfile"]["error"]){
case 1:
echo "<script>alert ('上传文件超过了php.ini中upload_max_filesize这个选项设置的值');history.go(-1)</script>";
break;
case 2:
echo "<script>alert ('上传的文件大小超过了HTML表单中MAX_FILE_SIZE选项指定的值');history.go(-1)</script>";
break;
case 3:
echo "<script>alert ('文件只有被部分上传');history.go(-1)</script>";
break;
case 4:
echo "<script>alert ('没有文件上传');history.go(-1)</script>";
break;
}
exit;
}else{
if(is_uploaded_file($_FILES["myfile"]["tmp_name"])){
if($filesize<1024){
if(move_uploaded_file($_FILES["myfile"]["tmp_name"],$copyto)){
echo "上传文件成功;上传文件大小为".$_FILES["myfile"]["size"]/1024 ."kb";
}else{
echo "上传文件失败";
}
}else{
echo "文件大小超过了限制";
}
}
}
?>
精品好课