首先跨域的需求是必须的,由程序架构所决定。
关于跨域那最先想到的还是jq的ajax的jsonp,可是jsonp只能使用get的方式,图片数据太大有可能就不稳定。最终决定使用formdata封装file对象,使用XMLHttpRequest对象发送请求数据。
为了模拟跨域,分别在本地的两个服务器localhost:80和localhost:8090部署后端和前端的代码
前端代码:
<script>
//第一步,从剪贴板获取file对象
document.addEventListener('paste', function(event) {
var items = (event.clipboardData && event.clipboardData.items) || [];
var file = null;
if (items && items.length) {
for (var i = 0; i < items.length; i++) {
if (items[i].type.indexOf('image') !== -1) {
file = items[i].getAsFile();
break;
}
}
}
if(!file){
return;
}
//第二步,实现预览,利用FileReader对象实现将file对象转化为base64位字符串
var reader = new FileReader();
reader.onload = function(e){
// 通过e.target.result取到base64然后上传
// 作为src设到image标签上预览
var img=document.createElement('img');
img.src=e.target.result;
img.width=110;
img.height=100;
document.getElementById("box").appendChild(img);
}
reader.readAsDataURL(file); //此处的file为上面得到的文件对象
//第三步,实现上传,
//【1】使用XMLHttpRequest对象post跨域异步上传文件,
//【2】使用formdata对象封装file对象数据
var formdata = new FormData();
formdata.append('file', file);
var xhr = new XMLHttpRequest();
xhr.open("POST", "http://192.168.1.115/uploadfile/file.php", true);
xhr.onload=function(){
var json=JSON.parse(xhr.responseText);
if(json.state==1){
alert('上传成功');
}
}
xhr.send(formdata);
});
</script>
html:用以预览图片容器
<div id="box">
</div>
php:后端
<?php
header("Access-Control-Allow-Origin:*");//接收跨域请求设置
if($_FILES['file']['size'])
{
$date=date('Ymd');
$path="./upload/".$date.'/';
if(!is_dir($path)){
mkdir($path,0777,true);
}
$name= $path.uniqid().'.png';
if(copy($_FILES['file']['tmp_name'], "$name"))
{
$arr['state']=1;
$arr['url']=$name;
}else{
$arr['state']=222;
}
}else{
$arr['state']=111;
}
echo json_encode($arr);
exit;
?>
知识点详述:
【1】跨域
- 跨域,指的是从一个域名去请求另外一个域名的资源。即跨域名请求。
- 跨域时,浏览器不能执行其他域名网站的脚本,是由浏览器的同源策略造成的,是浏览器施加的安全限制。
- 跨域的严格一点来说就是只要协议,域名,端口有任何一个的不同,就被当作是跨域。
【2】同源策略
- 同源策略是由 Netscape 公司提出的一个著名的安全策略,所有支持 JavaScript 的浏览器都会使用这个策略
- 所谓同源是指,域名,协议,端口相同。
- 当页面在执行一个脚本时会检查访问的资源是否同源,如果非同源,那么在请求数据时,浏览器会在控制台中报一个异常,提示拒绝访问。
使用FileReader对象,web应用程序可以异步的读取存储在用户计算机上的文件(或者原始数据缓冲)内容,可以使用File对象或者Blob对象来指定所要处理的文件或数据。
FileReader通过异步的方式读取文件内容,结果均是通过事件回调获取,下面是一个读取本地txt文件内容的例子:
var input = document.getElementById("file"); //input file
input.onchange = function(){
var file = this.files[0];
if(!!file){
//读取本地文件,以gbk编码方式输出
var reader = new FileReader();
reader.readAsText(file,"gbk");
reader.onload = function(){
//读取完毕后输出结果
console.log(this.result);
}
}
}
读取读片文件为base64位字符串
var reader = new FileReader();
reader.onload = function(e){
// 通过e.target.result取到base64然后上传
// 作为src设到image标签上预览
var img=document.createElement('img');
img.src=e.target.result;
img.width=110;
img.height=100;
document.getElementById("box").appendChild(img);
}
reader.readAsDataURL(file); //此处的file为上面得到的文件对象
【3】FormData对象
- FormData对象用以将数据编译成键值对,以便用
XMLHttpRequest
来发送数据 - 利用一些键值对来模拟一系列表单控件:即将form中的所有表单元素的name和value组装成一个queryString;
- 异步上传二进制文件。与普通Ajax相比,使用FormData的最大优点:可以异步上传二进制文件。
Formdata对象创建
1.你可以自己创建一个FormData
对象,然后调用它的append()
方法来添加字段
var formData = new FormData();
formData.append("username", "Groucho");
formData.append("accountnum", 123456); //数字123456会被立即转换成字符串 "123456"
2.通过HTML表单创建FormData对象
想要构造一个包含Form表单数据的FormData对象,需要在创建FormData对象时指定表单的元素。
var formData = new FormData(someFormElement);
3.你还可以在创建一个包含Form表单数据的FormData对象之后和发送请求之前,附加额外的数据到FormData对象里
var formElement = document.querySelector("form");
var formData = new FormData(formElement);
var request = new XMLHttpRequest();
request.open("POST", "submitform.php");
formData.append("serialnumber", serialNumber++);
request.send(formData);