Axios 上传文件

摘要

记录一个今天遇到的问题:使用 axio 上传文件过程中,传入 formData 数据,然后提示 the request was rejected because no multipart boundary was found。首先,确定这个接口是可以使用的。

如何使用 Axios 上传文件

首先需要设置 Axios 的 headers 里面的Content-Typemultipart/form-data;charset=utf-8。然后就是传入的数据必须为 FormData 数据类型。这样完成了一个初步的上传文件设置。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
// import axios from "axios";
import { baseConfig, debugUser } from "../config/api.config";
import config from "../config/host.config";
import utils from "../js/utils";
import { Toast } from "vant";

// 请求发出前
axios.interceptors.request.use(async (config) => {
// 上传文件

if (
config.data &&
Object.prototype.toString.call(config.data) == "[object FormData]"
) {
config.headers["Content-Type"] = "multipart/form-data;charset=utf-8";
config.transformRequest = [
function (data) {
return data;
},
];
}

if (config.params && typeof config.params != "string")
config.params = utils.filterNull(config.params);
if (process.env.NODE_ENV !== "production") {
//如果是开发环境
for (const key in debugUser) config.headers[key] = debugUser[key];
}
if (typeof bsch != "undefined") {
let autho = () => {
return new Promise((resolve, reject) => {
bsch.autho((resp) => {
resolve(resp);
});
});
};
let resp = await autho();
config.headers["schoolId"] = resp.schoolId;
config.headers["roleId"] = resp.roleId;
config.headers["userId"] = resp.userId;
}

return config;
});

// http response 拦截器
axios.interceptors.response.use(
(response) => {
let { data, status } = response;
return handeCallback(data, status);
},
function axiosRetryInterceptor(err) {
console.log(err.message);
console.log(err.message.indexOf("exceeded"));
if (err.message.indexOf("exceeded") > -1) Toast.fail("网络超时!");
}
);

const createApi = (url, params = null, method = "GET") => {
method = method.toLocaleUpperCase();
if (params == null) params = {};
const baseConfigCopy = {
...baseConfig,
url,
method,
data: method === "POST" || method === "PUT" ? params : null,
params: method === "GET" || method === "DELETE" ? params : null,
};

try {
return axios(baseConfigCopy);
} catch (error) {
console.error("error:" + error);
return new Promise((reject) => reject(error));
}
};

function createURL(url, param) {
var paramStr = "";
for (let key in param) {
if (param.hasOwnProperty(key)) {
const element = param[key];
var link = "&" + key + "=" + element;
paramStr += link;
}
}
url = url + "?" + paramStr.substr(1);
url = encodeURI(url);
return url.replace(" ", "");
}

function handeCallback(resp, resCode) {
var respStr = resp;
if (typeof respStr === "string") {
respStr = respStr.replace(/(\r\n)|(\n)|(\r)/g, "<br>");
respStr = respStr.replace(/(\t)/g, " ");
respStr = respStr.replace(/☊/g, "'");
respStr = respStr.replace(/♤/g, "\\");
respStr = respStr.replace(/♢/g, "/");
respStr = respStr.replace(/♧/g, '"');
try {
resp = JSON.parse(respStr);
} catch (error) {
alert("网络连接错误");
}
}

if (resCode == 200) {
if (resp.State || resp.code === 0) {
return resp.data;
} else {
throw resp.msg;
}
} else {
console.error(resCode, resp);
throw typeof resp;
}
}

export { createApi };

如果你设置了 header 头部的信息,然后用了 formData 数据。在接口调用的时候提示了 the request was rejected because no multipart boundary was found这个错误。

原因

某些情况下,浏览器不会给你的 Content-Type 上加上 boundary,那么就会提示这个错误。造成这个错误的原因也还有 formData 数据经过 post 之后被序列化了,所以在请求接口之前的拦截中加入如下代码

1
2
3
4
5
config.transformRequest = [
function (data) {
return data;
},
];

官方文档中对transformRequest的解释如下
transformRequest 允许在向服务器发送前,修改请求数据只能用在 ‘PUT’, ‘POST’ 和 ‘PATCH’ 这几个请求方法后面数组中的函数必须返回一个字符串,或 ArrayBuffer,或 Stream