本文详细解析Web前端实现头像上传至阿里云OSS的完整流程。核心步骤包括:利用FileReader将图片转为Base64进行本地预览,去除Data URI头部后转换为Blob对象,通过首次POST请求获取OSS上传地址,最后执行PUT请求完成文件上传。文中提供了基于AngularJS的完整代码示例及关键注意事项。
前端头像上传整体流程概述
本文分享一个简易的头像上传实现方案,主要流程如下:
图片Base64转换与预览实现
第一步,将用户选择的图片文件转换为Base64字符串。
function preview(file) {//预览图片得到图片base64
var prevDiv = document.getElementById('preview');
if (file.files && file.files[0]) {
var reader = new FileReader();
reader.onload = function(evt){
prevDiv.innerHTML = '<img src="' + evt.target.result + '" />';
}
reader.readAsDataURL(file.files[0]);
} else {
prevDiv.innerHTML = '<div class="img" style="filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(sizingMethod=scale,src=\'' + file.value + '\'"></div>';
}
}
上述方法实现了图片的Base64预览功能,开发者可通过控制台打印查看Base64字符串的具体内容。
Base64去头处理与Blob对象生成
第二步,根据阿里云OSS的上传规范,对Base64字符串进行预处理,去除头部信息。
var binaryblob = function (s, type) {//blob对象
var byteString = atob(s);
var array = [];
for (var i = 0; i < byteString.length; i++) {
array.push(byteString.charCodeAt(i));
}
return new Blob([new Int8Array(array)], {type: type});
};
var binaryPictureBlob = function (dataUrl, filterHead) {//上传base64去头
var s = filterHead ? dataUrl.replace(/^data:image\/(png|jpeg|pjpeg|bmp|gif|x-png);base64,/, "") : dataUrl;
return binaryblob(s, "image/jpeg");
};
处理后的Base64数据被转换为Blob对象,以便后续上传至阿里云。建议将此封装方法置于service或factory中,以便在需要图像上传功能时直接调用,避免代码冗余并提高复用性,不建议直接写在controller内。
首次请求:获取阿里云上传元数据
第三步,执行第一次网络请求。
$scope.save=function(){//保存
var pic=binaryPictureBlob($('#preview img').attr('src'),true);//调用该方法得到上传数据
console.log(pic);
$http({//接口参数
url:'',
method:'',
headers:{},
data:{}
}).success(function(data){
console.log(data);
//这里讲进行第二次请求
}).error(function(err1,header1,config1,status1){//处理响应失败
console.log(err1,header1,config1,status1);
})
}
点击保存按钮后,首先发起请求至本地服务器,主要目的是提交图片的相关标记信息。请求成功后,服务器会返回该图片对应的阿里云访问地址以及用于上传的OSS地址。需要注意的是,此时图片地址暂时无法直接访问。
二次请求:执行OSS文件上传及注意事项
第四步,执行第二次网络请求以完成实际文件上传。
$http({
method:'PUT',
url:data.UrlForPut,
headers: {
'Content-Type':' ',
},
data:pic//图像base64字符串去头等处理后的图片信息blob
}).success(function(data2){
$scope.imgSrc=data.Url;//将服务器的数据的url赋值图片链接
}).error(function(err2,header2,config2,status2){//处理响应失败
console.log(err2,header2,config2,status2);
});
注意事项:
此时请求的URL应为第一次请求返回的固定上传地址(例如示例中的--data.UrlForPut)。
在设置请求头部时,需特别注意Content-Type的写法,避免阿里云上传报错,具体格式应严格遵循阿里云的要求。
第二次请求成功后,最终可用的图片地址应为第一次请求返回的该图像访问地址(此处存在常见错误点,切勿错误地写成data2.Url)。
第五步,至此流程应已顺利完成,可以正常展示上传的图片。
最后附上完整代码示例,欢迎指正。 友情提示:在复制代码进行测试时,请自行补充必要的请求参数。
<!DOCTYPE html>
<html ng-app="webPhotos">
<head lang="zh-CN">
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<title>photos</title>
<style>
div{text-align:center;border:1px solid #ddd;}
button,div{margin:10px auto}
button{border:0;width:200px;height:30px;line-height:30px;font-size:1pc;color:#333;background-color:#0ff;cursor:pointer;border-radius:5px}
button:hover{background-color:#db7093}
#preview,.show-img{width:200px;height:200px;}
#preview img,.show-img img{width:100%;height:100%;}
.file{position:relative;display:block;width:200px;height:30px;line-height:30px;background:#9acd32;border-radius:5px;margin:10px auto;overflow:hidden;color:#1e88c7;text-decoration:none;text-indent:0}
.file input{position:absolute;font-size:75pt;right:0;top:0;opacity:0}
.file:hover{background:#aadffd;border-color:#78c3f3;color:#004974;text-decoration:none}
</style>
</head>
<body>
<div ng-controller="photos">
<a href="javascript:;" class="file">
<span>选择文件</span>
<input type="file" onchange="preview(this)" />
</a>
<button class="save" ng-click="save()">保存</button>
<h2>头像预览</h2>
<div id="preview"></div>
<h2>上传成功后展示头像</h2>
<div class="show-img">
<img ng-src={{imgSrc}} alt=""/>
</div>
</div>
<script type="text/javascript" src="https://cdn.bootcss.com/jquery/1.11.3/jquery.min.js"></script>
<script src="http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"></script>
<script>
function preview(file) {//预览图片得到图片base64
var prevDiv = document.getElementById('preview');
if (file.files && file.files[0]) {
var reader = new FileReader();
reader.onload = function(evt){
prevDiv.innerHTML = '<img src="' + evt.target.result + '" />';
}
reader.readAsDataURL(file.files[0]);
} else {
prevDiv.innerHTML = '<div class="img" style="filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(sizingMethod=scale,src=\'' + file.value + '\'"></div>';
}
}
//以上代码最好写在service或factory里
angular.module('webPhotos',['ng'])
.controller('photos',function($scope,$http){
var binaryblob = function (s, type) {//blob对象
var byteString = atob(s);
var array = [];
for (var i = 0; i < byteString.length; i++) {
array.push(byteString.charCodeAt(i));
}
return new Blob([new Int8Array(array)], {type: type});
};
var binaryPictureBlob = function (dataUrl, filterHead) {//上传base64去头
var s = filterHead ? dataUrl.replace(/^data:image\/(png|jpeg|pjpeg|bmp|gif|x-png);base64,/, "") : dataUrl;
return binaryblob(s, "image/jpeg");
};
$scope.save=function(){//保存
var pic=binaryPictureBlob($('#preview img').attr('src'),true);//调用该方法得到上传数据
$http({//接口参数
url:'',
method:'',
headers:{},
data:{}
}).success(function(data){//此时上传到本地服务器成功,实际上只是上传了与此图片有关的标记,图片信息还未上传
$http({
method:'PUT',
url:data.UrlForPut,//上传到本地服务器已经生成地址,但要上传到阿里云后地址才生效有上传的图像显示
headers: {
'Content-Type':' ',//避免阿里云上传时报错或者根据阿里云要求上传header
},
data:pic//图像base64字符串去头等处理后的图片信息
}).success(function(data2){//将图像信息从服务器上传到阿里云
$scope.imgSrc=data.Url;//将服务器的数据的url赋值图片链接
}).error(function(err2,header2,config2,status2){//处理响应失败
console.log(err2,header2,config2,status2);
});
}).error(function(err1,header1,config1,status1){//处理响应失败
console.log(err1,header1,config1,status1);
})
}
})
</script>
</body>
</html>
更多精彩内容请参考专题《ajax上传技术汇总》,《javascript文件上传操作汇总》和《jQuery上传操作汇总》进行学习。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持本站。