前端向又拍云上传文件,报错Refused to set unsafe header "Date"
遇到的问题
调用又拍云接口的时遇到了一个问题记录;
在每次调用又拍云接口时,先通过签名认证拿到了签名和Date。
如果请求头不加 Date
又拍云服务器返回数据如下
{
"msg":"need date header",
"code":40100001,
"id":"XXXXX"
}
接口需要Date参数;
给请求头加上Date参数,浏览器会报错。
Refused to set unsafe header "Date"
在Chrome中使用REST API 发送请求时,在请求的HTTP Header中添加Date参数,Chrome会提示:Refused to set unsafe header “Date” ,因为Chrome按照W3C的要求执行,Date为不安全字符(详情查看http://www.w3.org/TR/XMLHttpRequest/#the-setrequestheader-method)
匹配以下不安全字符时,将被终止
w3c规定,当请求的header匹配以下不安全字符时,将被终止
Accept-Charset
Accept-Encoding
Connection
Content-Length
Cookie
Cookie2
Content-Transfer-Encoding
Date
Expect
Host
Keep-Alive
Referer
TE
Trailer
Transfer-Encoding
Upgrade
User-Agent
Via
Date为默认的字符,不能自定义传入,所以请求被拒绝了。
而又拍云又需要在请求头上加上Date,所以导致了又拍云接口不能顺利调用。
我给upyun发工单后,发现他们也是有对应的解决方案的
解决方案
前端跨域上传的时候,可以使用 X-Date
参数替换 Date
参数。
另外如果您使用的 FORM API
方式进行上传,签名和 HTTP
请求过程中可以不使用 Date
参数。
演示方案
HTML 文件
hash文件和jquery就不贴了;
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<script src="hash.js"></script>
<script src="jquery-1.9.0.min.js"></script>
<script>
$(function(){$("body").html("<div id='fileinput'></div><div id='fileinfo'></div>");$("#fileinput").html("<input id='fileupload' type='file' name='file' onchange='ufload(this)'/><br/><br/>");});
function ufload(obj) {
var bucketname="xxx"; //服务名
var username="xxx"; //操作员账号
var password="xxx"; //操作员密码
var save_key="/{filename}{.suffix}";
var url="http://v0.api.upyun.com/"+bucketname;
var file=$(obj).get(0).files[0];
var fileinfo=document.getElementById("fileinfo");
var policy=btoa(JSON.stringify({"bucket": bucketname, "save-key": save_key, "expiration": parseInt(Date.parse(new Date())+3600)}));
var signature="UPYUN "+username+":"+b64hamcsha1(HexMD5.MD5(password).toString(HexMD5.enc.Hex), "POST&/"+bucketname+"&"+policy);
fileinfo.innerHTML="文件名称: "+file.name+"<br/>"+"文件大小: "+file.size+"<br/>"+"文件类型: "+file.type+"<br/><br/>"+
"<div id='progress' style='width:300px;height:14px;border:1px solid #ddd;padding-top:0px;border-radius:4px;display:none'><div id='bar' style='float:left;background-color:#62BFFF; width:0%; height:14px; border-radius:3px;'></div><div id='percent' style='float:left;width:0px;display:inline-block; top:0px;font-size:10px;'></div>";
var xhrOnProgress=function(fun){
xhrOnProgress.onprogress=fun;
return function(){
var xhr=$.ajaxSettings.xhr();
if (typeof xhrOnProgress.onprogress!=='function'){
return xhr;
}
if (xhrOnProgress.onprogress&&xhr.upload){
xhr.upload.onprogress=xhrOnProgress.onprogress;
}
return xhr;
}
}
var formData=new FormData();
formData.append("file",file);
formData.append("policy",policy);
formData.append("authorization",signature);
$.ajax({
url:url,
type:"POST",
data:formData,
contentType:false,
processData:false,
xhr:xhrOnProgress(function(e){
var percent=Math.round(e.loaded*100/e.total);
$("#progress").show();
$("#percent").text(percent+"%");
$("#bar").width(percent+'%');
}),
success:function(data, textStatus,xhr){
$("#progress").hide();
fileinfo.innerHTML+="上传成功!<br/><br/>";
for (var key in JSON.parse(data)){
fileinfo.innerHTML+=key+": "+JSON.parse(data)[key]+"<br/>";
}
},
error:function(xhr){
$("#progress").hide();
fileinfo.innerHTML+="上传失败!<br/><br/>";
for (var key in JSON.parse(xhr.responseText)){
fileinfo.innerHTML+=key+": "+JSON.parse(xhr.responseText)[key]+"<br/>";
}
}
});
}
</script>
</head>
<body></body>
</html>