request.js 前端通用文件批量下载,前端压缩文件(变成压缩包)

文章介绍了如何使用axios创建HTTP请求,并设置了请求和响应拦截器,包括处理token验证、防止数据重复提交以及错误处理。同时,还展示了如何实现文件下载,支持单个文件和ZIP文件的下载功能。
摘要由CSDN通过智能技术生成

import axios from 'axios'

import { ElNotification , ElMessageBox, ElMessage, ElLoading } from 'element-plus'

import { getToken } from '@/utils/auth'

import errorCode from '@/utils/errorCode'

import { tansParams, blobValidate } from '@/utils/ruoyi'

import cache from '@/plugins/cache'

import { saveAs } from 'file-saver'

import useUserStore from '@/store/modules/user'

import JSZip from "jszip";

let downloadLoadingInstance;

// 是否显示重新登录

export let isRelogin = { show: false };

axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8'

// 创建axios实例

const service = axios.create({

// axios中请求配置有baseURL选项,表示请求URL公共部分

baseURL: import.meta.env.VITE_APP_BASE_API,

// 超时

timeout: 120000

})

// request拦截器

service.interceptors.request.use(config => {

// 是否需要设置 token

const isToken = (config.headers || {}).isToken === false

// 是否需要防止数据重复提交

const isRepeatSubmit = (config.headers || {}).repeatSubmit === false

if (getToken() && !isToken) {

config.headers['Authorization'] = 'Bearer ' + getToken() // 让每个请求携带自定义token 请根据实际情况自行修改

}

// get请求映射params参数

if (config.method === 'get' && config.params) {

let url = config.url + '?' + tansParams(config.params);

url = url.slice(0, -1);

config.params = {};

config.url = url;

}

if (!isRepeatSubmit && (config.method === 'post' || config.method === 'put')) {

const requestObj = {

url: config.url,

data: typeof config.data === 'object' ? JSON.stringify(config.data) : config.data,

time: new Date().getTime()

}

const sessionObj = cache.session.getJSON('sessionObj')

if (sessionObj === undefined || sessionObj === null || sessionObj === '') {

cache.session.setJSON('sessionObj', requestObj)

} else {

const s_url = sessionObj.url; // 请求地址

const s_data = sessionObj.data; // 请求数据

const s_time = sessionObj.time; // 请求时间

const interval = 1000; // 间隔时间(ms),小于此时间视为重复提交

if (s_data === requestObj.data && requestObj.time - s_time < interval && s_url === requestObj.url) {

const message = '数据正在处理,请勿重复提交';

console.warn(`[${s_url}]: ` + message)

return Promise.reject(new Error(message))

} else {

cache.session.setJSON('sessionObj', requestObj)

}

}

}

return config

}, error => {

console.log(error)

Promise.reject(error)

})

// 响应拦截器

service.interceptors.response.use(res => {

// 未设置状态码则默认成功状态

const code = res.data.code || 200;

// 获取错误信息

const msg = errorCode[code] || res.data.msg || errorCode['default']

// 二进制数据则直接返回

if(res.request.responseType === 'blob' || res.request.responseType === 'arraybuffer'){

//获取后端请求头中文件名

res.data.filename = res.headers['content-disposition']

return res.data

}

if (code === 401) {

if (!isRelogin.show) {

isRelogin.show = true;

ElMessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', { confirmButtonText: '重新登录', cancelButtonText: '取消', type: 'warning' }).then(() => {

isRelogin.show = false;

useUserStore().logOut().then(() => {

location.href = '/index';

})

}).catch(() => {

isRelogin.show = false;

});

}

return Promise.reject('无效的会话,或者会话已过期,请重新登录。')

} else if (code === 500) {

ElMessage({ message: msg, type: 'error' })

return Promise.reject(new Error(msg))

} else if (code === 601) {

ElMessage({ message: msg, type: 'warning' })

return Promise.reject(new Error(msg))

} else if (code !== 200) {

ElNotification.error({ title: msg })

return Promise.reject('error')

} else {

return Promise.resolve(res.data)

}

},

error => {

console.log('err' + error)

let { message } = error;

if (message == "Network Error") {

message = "后端接口连接异常";

} else if (message.includes("timeout")) {

message = "系统接口请求超时";

} else if (message.includes("Request failed with status code")) {

message = "系统接口" + message.substr(message.length - 3) + "异常";

}

ElMessage({ message: message, type: 'error', duration: 5 * 1000 })

return Promise.reject(error)

}

)

// 通用下载方法

export function download(url, params, filename, config) {

downloadLoadingInstance = ElLoading.service({ text: "正在下载数据,请稍候", background: "rgba(0, 0, 0, 0.7)", })

return service.post(url, params, {

transformRequest: [(params) => { return tansParams(params) }],

headers: { 'Content-Type': 'application/x-www-form-urlencoded' },

responseType: 'blob',

...config

}).then(async (data) => {

const isLogin = await blobValidate(data);

if (isLogin) {

const blob = new Blob([data])

saveAs(blob, filename)

} else {

const resText = await data.text();

const rspObj = JSON.parse(resText);

const errMsg = errorCode[rspObj.code] || rspObj.msg || errorCode['default']

ElMessage.error(errMsg);

}

downloadLoadingInstance.close();

}).catch((r) => {

console.error(r)

ElMessage.error('下载文件出现错误,请联系管理员!')

downloadLoadingInstance.close();

})

}

export async function downloadZip(url, params) {

try {

downloadLoadingInstance = ElLoading.service({ text: "正在下载数据,请稍候", background: "rgba(0, 0, 0, 0.7)", })

const downloadPromises = params.map(async (item) => {

const res = await service.post(url, item, {

transformRequest: [(item) => { return tansParams(item) }],

headers: { 'Content-Type': 'application/x-www-form-urlencoded' },

responseType: 'blob',

});

const isLogin = await blobValidate(res);

if (isLogin) {

return {

blob: new Blob([res]),

fileName: getFilename(res.filename)

};

} else {

const rspObj = JSON.parse(await res.text());

const errMsg = errorCode[rspObj.code] || rspObj.msg || errorCode['default']

ElMessage.error(errMsg);

return null;

}

});

const blobs = await Promise.all(downloadPromises);

const validBlobs = blobs.filter(blob => blob !== null);

if (validBlobs.length > 0) {

const zip = new JSZip();

validBlobs.forEach(({ blob, fileName }) => {

zip.file(fileName, blob);

});

const zipBlob = await zip.generateAsync({ type: 'blob' });

saveAs(zipBlob, 'xxx.zip');

downloadLoadingInstance.close();

} else {

downloadLoadingInstance.close();

console.error('没有可下载的文件');

ElMessage.error('没有可下载的文件');

}

} catch (error) {

downloadLoadingInstance.close();

console.error('文件下载失败: ', error);

ElMessage.error('文件下载失败');

}

}


 

function getFilename(str) {

const regex = /filename=(.*)/;

const match = regex.exec(str);

if (match && match.length > 1) {

return match[1];

} else {

return null; // 如果没有匹配到文件名,返回null或者你认为合适的默认值

}

}

export default service

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值