axios封装
request.js
import Vue from "vue"
import axios from "axios"
import { Message } from "element-ui"
import * as streamSaver from "streamsaver"
import vm from "@/main.js"
let loading
axios.defaults.withCredentials = true
// 创建axios实例
const service = axios.create({
baseURL: "/",
timeout: 30000,
headers: {
"Content-Type": "application/json",
},
})
// request拦截器
service.interceptors.request.use(
(config) => {
loading = Vue.prototype.$loading({
lock: true,
text: "Loading",
spinner: "el-icon-loading",
background: "rgba(0, 0, 0, 0.7)",
})
if (localStorage.token && localStorage.userId) {
config.headers["token"] = `${localStorage.token}`
config.headers["userId"] = `${localStorage.userId}`
}
if (config.method === "post") {
config.data = JSON.stringify({
...config.data,
})
}
return config
},
(error) => {
Promise.reject(error)
}
)
// response拦截器
service.interceptors.response.use(
(response) => {
loading.close()
const res = response.data
// 文档 content-type 类型
let docs = ['application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'application/msword', 'application/vnd.ms-excel', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'text/plain']
// 图片 content-type 类型
let img = ['application/octet-stream', 'image/jpeg', 'image/png', 'image/gif', 'image/bmp', 'image/svg+xml', 'image/webp']
// 未知 content-type 类型
let file = ['application/octet-stream']
const header = response.headers['content-type'] || ''
if ([...docs, ...img, ...file].includes(header.replace(';charset=utf-8', ''))) {
return res
}
handleResponseData(res)
},
(error) => {
loading.close()
Message({
message: "服务器异常",
type: "error",
duration: 3 * 1000,
})
return Promise.reject(error)
}
)
// 用于文件上传(不需要Qs.stringify,直接添加form-data就行)
const fileService = axios.create({
baseURL: "/",
timeout: 30000,
headers: {
"Content-Type": "multipart/form-data",
},
})
// request拦截器
fileService.interceptors.request.use(
(config) => {
loading = Vue.prototype.$loading({
lock: true,
text: "Loading",
spinner: "el-icon-loading",
background: "rgba(0, 0, 0, 0.7)",
})
return config
},
(error) => {
loading.close()
Promise.reject(error)
}
)
// response拦截器
fileService.interceptors.response.use(
(response) => {
const res = response.data
loading.close()
handleResponseData(res)
},
(error) => {
loading.close()
Message({
message: error.message,
type: "error",
duration: 3 * 1000,
})
return Promise.reject(error)
}
)
/**
* 处理响应数据
* @param res 响应数据
* @returns
*/
function handleResponseData(res) {
if (res.code === 0 || res.code === 200 ) {
return res
} else if (res.code === 500) {
Message({
message: res.msg || res.message || '系统异常',
type: "error",
duration: 10 * 1000,
})
return res
} else if (res.code === 401) {
Message({
message: "请登录",
type: "warning",
duration: 3 * 1000,
})
localStorage.clear()
vm.$router.push("/")
return res
} else {
Message({
message: "连接超时",
type: "error",
duration: 3 * 1000,
})
return Promise.reject(res)
}
}
/**
* get方法,对应get请求
* @param {String} url [请求的url地址]
* @param {Object} params [请求时携带的参数]
*/
export function get(url, params){
return new Promise((resolve, reject) =>{
service.get(url, {
params: params
}).then(res => {
resolve(res);
}).catch(err =>{
reject(err)
})
});
}
/**
* post方法,对应post请求
* @param {String} url [请求的url地址]
* @param {Object} params [请求时携带的参数]
*/
export function post(url, params, config = {}) {
return new Promise((resolve, reject) => {
service.post(url, params, {
...config
})
.then(res => {
resolve(res);
})
.catch(err =>{
reject(err)
})
});
}
/**
* @description 一般导出(小文件下载) post请求
* @param { String } url 下载路径
* @param { Object } data 下载参数
*/
export const download = function(url, data = {}) {
service({ url, method: 'POST', data, responseType: 'blob' }).then(blob => {
const fileNameMatch = blob['content-disposition'].match(/filename\*?=['"]?(?:UTF-\d['"]*)?([^;\r\n"']*)['"]?;?/i)
const encodedFileName = fileNameMatch ? fileNameMatch[1] : null
const decodedFileName = encodedFileName ? decodeURIComponent(encodedFileName) : null
const downloadLink = document.createElement('a')
downloadLink.href = URL.createObjectURL(blob)
downloadLink.download = decodedFileName
downloadLink.click()
URL.revokeObjectURL(downloadLink.href)
})
}
/**
* @description 导出大文件
* @param { String } url 下载路径
* @param { String } fileName 文件名字
*/
export const downloadResource = async function (url, fileName) {
let filename = fileName
if (!fileName) {
filename = url.substring(url.lastIndexOf('/') + 1);
}
return fetch(url, {
method: 'GET',
cache: 'no-cache',
}).then(res => {
const fileStream = streamSaver.createWriteStream(filename,{
//增加小视图,体现下载进度条与总大小
size : res.headers.get("content-length")
})
const readableStream = res.body
if (window.WritableStream && readableStream.pipeTo) {
return readableStream.pipeTo(fileStream)
}
window.writer = fileStream.getWriter()
const reader = res.body.getReader()
const pump = () => reader.read()
.then(res => res.done
? window.writer.close()
: window.writer.write(res.value).then(pump))
pump()
})
}
/**
* 上传文件
* @param url 请求路径
* @param formData 上传参数
* @returns
*/
export const upload = function(url, formData = {}) {
return new Promise((resolve, reject) => {
fileService.post(url, formData).then(res => {
resolve(res);
}) .catch(err =>{
reject(err)
})
});
}
export { service, fileService }