上传图片的那些事儿
1.仅支持高版本刘浏览器上传
var param = new FormData();
param.append('imgData', file);
var xhr = new XMLHttpRequest();
xhr.addEventListener("load", uploadCompleteHandler, false);
xhr.addEventListener("error", uploadFailedHandler, false);
xhr.addEventListener("abort", uploadCanceledHandler, false);
xhr.open("POST", url);
xhr.send(param);
XMLHttpRequest
ie5-6使用的是ActiveX,而非XMLHttpRequest
1998年 XMLHTTP
2002年8月,XMLHttpRequest Level 2草案提出
创建兼容的XMLHttpRequest
var XMLHttp=null;
if (window.XMLHttpRequest)
{
XMLHttp=new XMLHttpRequest()
}else if (window.ActiveXObject)
{
XMLHttp=new ActiveXObject("Microsoft.XMLHTTP")
}

FormData

XMLHttpRequest Level 2 中新增接口
需求增加进度条功能
XMLHttpRequest中有一个upload对象upload是一个XMLHttpRequestUpload
var param = new FormData();
param.append('imgData', file);
var xhr = new XMLHttpRequest();
xhr.upload.addEventListener("progress", uploadProgressHandler, false);
xhr.addEventListener("load", uploadCompleteHandler, false);
xhr.addEventListener("error", uploadFailedHandler, false);
xhr.addEventListener("abort", uploadCanceledHandler, false);
xhr.open("POST", url);
xhr.send(param);
https://segmentfault.com/a/1190000004322487
https://xhr.spec.whatwg.org/
需要支持跨域请求
方案:1.JSONP
方案2:CORS
jsonp仅支持get,PASS
CORS
全称: 跨域资源共享-Cross-origin resource sharing
服务器与浏览器共同实现
CORS兼容性

新需求:支持低版本浏览器
flash上传插件解决
市面上的上传插件如webUploader
自动切换上传方式,很方便
but
仅支持jq 1.10.0+的版本,万恶的1.6.4
选择SWFUploader
使用指南
Flash使用方式
方案2:swf放在服务器端,与结构同源,所以也支持跨域
方案1:swf放在自己项目中,使用crossdomain.xml
<?xml version="1.0" encoding="UTF-8"?>
<cross-domain-policy>
<allow-access-from domain="*"/>
</cross-domain-policy>
SWFUploader配置
setting = {
debug: false,
upload_url: url, //服务器接受文件路径
flash_url: "swf?ver=" + Math.random(), //上传的swf文件路径
//文件配置
file_post_name: "imgData", //服务器接受的文件数据key值
post_params: {
sessionId: opts.param.sessionId
}, //上传文件时带的参数
file_types: "*.bmp;*.jpeg;*.jpg;*.gif;*.png", //文件类型过滤配置
file_types_description: '浏览器图片格式', //上传文件类型描述
file_size_limit: opts.fileSizeLimit, //指定要上传的文件的最大体积,可以带单位,合法的单位有:B、KB、MB、GB,如果省略了单位,则默认为KB。该属性为0时,表示不限制文件的大小。
file_upload_limit: "200",
file_queue_limit: "1",
prevent_swf_caching: false,
preserve_relative_urls: false,
//按钮配置
button_placeholder_id: opts.id,
button_width: (opts.type == 'pop') ? 160 : 175,
button_height: (opts.type == 'pop') ? 100 : 109,
button_text: "<span></span>",
button_text_style: "",
button_text_left_padding: 0,
button_text_top_padding: 0,
button_action: SWFUpload.BUTTON_ACTION.SELECT_FILES,
button_disabled: false,
button_cursor: SWFUpload.CURSOR.HAND,
button_window_mode: "transparent",
custom_settings: {
index: opts.index
},
// 事件
file_dialog_start_handler: _self.fileDialogStart,
file_queued_handler: _self.fileQueued,
file_queue_error_handler: _self.fileQueueError,
file_dialog_complete_handler: _self.fileDialogComplete,
upload_progress_handler: _self.uploadProgress,
upload_error_handler: _self.uploadError,
upload_success_handler: _self.uploadSuccess,
upload_complete_handler: _self.uploadComplete
}
var swfupload = new SWFUpload(setting);
准备上传
but
上传完没回返回数据,有木有
重要的坑
flash在IE中上传的文件类型为 Accept 类型为text/*


高版本中使用XHR Accept 类型为*/*
服务端默认为*/*,需要单独配置接受flash发送的请求类型
增加登录验证(cookie)
XHR与FLASH 居然都不会自动携带cookie
顿时感觉为什么坑会不断呢,没办法有坑继续吧
登录验证添加后发现上传失败
XHR
withCredentials

var param = new FormData();
param.append('imgData', file);
var xhr = new XMLHttpRequest();
xhr.upload.addEventListener("progress", uploadProgressHandler, false);
xhr.addEventListener("load", uploadCompleteHandler, false);
xhr.addEventListener("error", uploadFailedHandler, false);
xhr.addEventListener("abort", uploadCanceledHandler, false);
xhr.open("POST", url);
xhr.withCredentials = true;
xhr.send(param);
server端也必须允许request能携带认证信息(即response header中包含Access-Control-Allow-Credentials:true)
cookie也算一种认证
PS:要特别注意一点,一旦跨域request能够携带认证信息,server端一定不能将Access-Control-Allow-Origin设置为*,而必须设置为请求页面的域名。
Flash
手动控制把cookie添加到请求头,或
使用swfupload.cookies.js来自动写入
Flash与XHR的cookie都带过去,
BUT
XHR版本你发现还是不会触发Success
经过与研发一起排查发现,被登录拦截器又一次拦截了
经过我的排查发现这么一个神奇的事情



OPTIONS请求
以为自己代码写错了,删除代码发现
多了这个监听就会发送OPTIONS请求:
xhr.upload.addEventListener("progress", _self.uploadProgress, false);
此为预检请求
触发预检请求的情况
简单请求与复杂请求
触发预检请求的情况
2.人为设置了对 CORS 安全的首部字段集合之外的其他首部字段。该集合为:
- Accept
- Accept-Language
- Content-Language
- Content-Type (but note the additional requirements below)
- DPR
- Downlink
- Save-Data
- Viewport-Width
- Width
触发预检请求的情况
Content-Type 的值不属于下列之一:
- application/x-www-form-urlencoded
- multipart/form-data
- text/plain
解决方法
研发端需要对请求类型过滤,当为OPTIONS时不需要进行cookie验证
THANKS
上传的图片的那些事儿
By codesniper
上传的图片的那些事儿
- 782