前端向又拍云上传文件,报错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>

AXIHE / 精选资源

浏览全部教程

面试题

学习网站

前端培训
自己甄别

前端书籍

关于朱安邦

我叫 朱安邦,阿西河的站长,在杭州。

以前是一名平面设计师,后来开始接接触前端开发,主要研究前端技术中的JS方向。

业余时间我喜欢分享和交流自己的技术,欢迎大家关注我的 Bilibili

关注我: Github / 知乎

于2021年离开前端领域,目前重心放在研究区块链上面了

我叫朱安邦,阿西河的站长

目前在杭州从事区块链周边的开发工作,机械专业,以前从事平面设计工作。

2014年底脱产在老家自学6个月的前端技术,自学期间几乎从未出过家门,最终找到了满意的前端工作。更多>

于2021年离开前端领域,目前从事区块链方面工作了