博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
解决Yapi 插件运行不支持文件上传的问题解决
阅读量:5904 次
发布时间:2019-06-19

本文共 3340 字,大约阅读时间需要 11 分钟。

背景

chrome 在 73 版本后,限制了 content-script 跨域请求目前只有一个解决办法,废弃 content-script 跨域请求,使用background.js 执行跨域请求,但这样有个最大的问题是无法支持文件上传

问题的背景如上。原先的yapi插件支持两种方式, 第一个是在content-script中进行请求,另外一个则是background进行请求,但是background需要依赖于content-script将请求的内容传递给到background中。

遇到的坑

一开始觉得这个问题其实不难解决,因为在content-script已经将所有的请求内容都获取到了,包括上传的文件(formdata格式)所以只要将内容传递给到background中即可

function sendAjaxByBack(id, req, successFn, errorFn) {    successFns[id] = successFn;    errorFns[id] = errorFn;    connect.postMessage({        id: id,        req: req    });}复制代码

只要将文件的formdata内容赋值到req中即可,结果发现在background中接收到的formdata的数据为空。翻阅了下google关于postMessage的api后发现如下:

消息必须是可被JSON序列化的,所以就是为什么formData的数据变成空的原因了。

解决方法

考虑了下,并不是说file的对象一定要用formdata已经包装传递,是否可以变成字符串的形式呢,这个时候我们可以想到可以把文件转换成base64进行传递,然后再解析回原先的文件对象即可了。

所以代码如下

function sendAjaxByBack(id, req, successFn, errorFn) {    successFns[id] = successFn;    errorFns[id] = errorFn;    if (req.headers['Content-Type'] === 'multipart/form-data') {        var formDatas = []        if (req.data) {            for (var name in req.data) {                formDatas.push({name, value: req.data[name], is_file: false});            }        }        if (req.files) {            let allPromise = [];            for (var name in req.files) {                let fileTransfer = new Promise(function (resolve, reject){                    var files = document.getElementById(req.files[name]).files;                    let file = files[0]                    var reader = new FileReader();                    reader.name = name;                    reader.fileName = file.name;                    reader.onload = function () {                        resolve({
name: this.name, value: this.result,is_file: true, fileName: this.fileName}); } reader.readAsDataURL(file); }) allPromise.push(fileTransfer); } Promise.all(allPromise).then(function(result){ formDatas = formDatas.concat(result); req.formDatas = formDatas; connect.postMessage({ id: id, req: req, }); }) }else { req.formDatas = formDatas; connect.postMessage({ id: id, req: req, }); } } else { connect.postMessage({ id: id, req: req }); }}复制代码

针对文件的发送转换成base64进行存储分别依次放到formdata的一个数组中,这里要区别部分是文件的类型,部分是普通的字符串,所以我们这里通过一个is_file进行区别是否是文件类型。

background.js中的处理

if (!req.headers['Content-Type'] || req.headers['Content-Type'] == 'application/x-www-form-urlencoded') {			req.headers['Content-Type'] = 'application/x-www-form-urlencoded';			req.data = formUrlencode(req.data);		}  else if (req.headers['Content-Type'] === 'multipart/form-data') {			delete req.headers['Content-Type'];			let formDatas = new FormData();			for (var item of req.formDatas) {				if (item.is_file) {					formDatas.append(item.name, dataURLtoFile(item.value, item.fileName))				}else {					formDatas.append(item.name, item.value);				}			}			req.data = formDatas;		}  else if (typeof req.data === 'object' && req.data) {			req.data = JSON.stringify(req.data);		}复制代码

针对content-Type为multipart/form-data的处理,声明一个formdata进行存储对应的数据

如此即可解决文件通过background进行文件上传的问题

转载于:https://juejin.im/post/5cde479b6fb9a07eb94f596b

你可能感兴趣的文章
disk磁盘管理与Linux驱动编写
查看>>
简单讲一下SpringMVC的执行流程?
查看>>
IBM更新Watson为数据密集型AI应用提速
查看>>
数通手稿留档——OSPF
查看>>
Linux系统用户和权限管理
查看>>
Script:列出数据库中子表上没有对应索引的外键
查看>>
oracle创建用户、表空间
查看>>
yum 报错:保护多库版本
查看>>
ZABBIX实现原理及架构详解
查看>>
tidb部署
查看>>
copy_constructor 复制构造函数2
查看>>
max-width
查看>>
DNS服务搭建
查看>>
Netapp 系统升级步骤
查看>>
如何查看linux版本
查看>>
Linux下的监控器之一Ganglia详解与部署
查看>>
Openstack 安装部署指南翻译系列 之 网络
查看>>
在Apache禁止访问目录前提下,能访问到其他目录的设置
查看>>
Android开发联机调试的准备
查看>>
虚拟化技术—docker容器—web UI篇
查看>>