var xhr = $.ajaxSettings.xhr();
var headers = $.extend({
'Upload-Offset': range_from,
'Content-Type': 'application/offset+octet-stream'
}, self.options.headers);
var options = {
type: 'PATCH',
url: self.fileUrl, // 图片后缀地址例如:/api/v1/upload/upload_resumable/default/default.zopen.standalone/c/4/c/4a94af6df4522ab6f8023e8a7f0b9.jpg
data: blob,
processData: false,
contentType: self.file.type,
cache: false,
xhr: function() {
return xhr;
},
headers: headers
};
$(xhr.upload).bind('progress', function(e) {
self.bytesWritten = bytesWrittenAtStart + e.originalEvent.loaded;
self._emitProgress(e);
});
this._jqXHR = $.ajax(options)
.fail(function(jqXHR, textStatus, errorThrown) {
var msg = jqXHR.responseText || textStatus || errorThrown;
self._emitFail(msg);
})
.done(function() {
if(range_to === self.file.size){
if (self.options.resetAfter === true) {
self._urlCache(false);
}
self._emitDone();
}else{
self._uploadFile(range_to);
}
});
};
上面url参数是图片后缀地址,服务端获取的request method 变成了GET,如果url改成非图片后缀地址,request method是正常的。
测试type参数为POST也是相同问题。
问题总结:发起Ajax请求,如果请求地址是一个图片后缀地址,浏览器把请求方式统一变成了GET
IOS系统没问题,部分安卓机型有问题,有问题的钉钉版本和浏览器user agnet 如下:
'HTTP_USER_AGENT': 'Mozilla/5.0 (Linux; U; Android 9; zh-CN; BKL-AL00 Build/HUAWEIBKL-AL00) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/57.0.2987.108 UCBrowser/11.9.4.974 UWS/2.13.1.52 Mobile Safari/537.36 AliApp(DingTalk/4.6.18) com.alibaba.android.rimet/11146596 Channel/227200 language/zh-CN',
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。
这个问题看起来是由于部分安卓设备上的浏览器或特定版本的钉钉客户端对Ajax请求的处理方式与标准不完全一致,尤其是在请求图片后缀URL时自动将HTTP方法从PATCH或POST转换为GET。这可能是由于这些客户端内置了某些针对静态资源(如图片)的优化策略,旨在减少不必要的POST/PUT/PATCH等非安全方法的使用,以避免潜在的安全风险或出于性能考虑。
要解决这个问题,可以尝试以下几种方案:
修改请求URL:既然问题仅在请求图片后缀URL时出现,可以考虑调整服务器端接口设计,避免直接使用文件扩展名作为路径的一部分,或者在图片URL前添加一个代理层或路由,使其不直接暴露文件扩展名。
使用FormData:尽管你已经设置了processData: false
和正确的contentType
,但尝试包裹数据到FormData
对象中有时能绕过某些客户端的特殊处理逻辑。示例如下:
var formData = new FormData();
formData.append('file', blob, 'filename'); // 注意这里的第三个参数是文件名,可以自定义
options.data = formData;
delete options.contentType; // 当使用FormData时,通常不需要手动设置contentType
预检请求(CORS)配置:确保服务器端正确配置了CORS(跨源资源共享),特别是对于非标准请求方法(如PATCH)。需要支持OPTIONS方法,并在响应头中包含Access-Control-Allow-Methods
,明确列出允许的方法(包括PATCH)。
分段上传替代方案:如果这个请求是为了实现大文件分段上传,考虑是否可以采用更通用且兼容性更好的上传方案,比如通过表单上传(虽然可能不支持断点续传)或利用成熟的文件上传库(如resumable.js、tus-js-client等),这些库通常有较好的兼容性处理。
用户教育与反馈:鉴于此问题只影响部分特定环境,可以考虑收集受影响用户的详细信息,并引导他们更新到最新版本的应用或更换其他浏览器尝试,同时向钉钉开发者社区或相关技术支持渠道反馈该问题,寻求官方解决方案或确认是否为已知问题。
客户端检测与降级策略:在前端代码中,根据User-Agent检测到是这些特定的安卓版本或钉钉客户端时,采取降级策略,比如提示用户当前环境不支持该功能或改用更传统的POST上传方式(即使这意味着牺牲一些特性,如断点续传)。
请根据实际情况选择合适的解决方案进行尝试。