前端对后端返回文件流及文件名称进行处理&node编写本地测试服务返回文件流

1 篇文章 0 订阅
1 篇文章 0 订阅

公司项目有导入和导出功能

后端导出接口返回的是文件流形式前端需要对文件名称以及文件流做额外处理
首先是请求部分

export function getExport(params){
	return request({
		url:'请求后端接口',
		method:'get',
		params,
		responseType:'blob',//這里需要设置一下返回类型,不然文件可能会下载后可能会有问题
		headers:{
			groupId:10111,//这里是我们公司项目自己需要的集团ID可以忽略
		}
	})
}

接下来是下载方法 注意fileName這个字段

function downLoad(fileName, data) {
  const filename = fileName
  const blob = new Blob([data], { type: 'application/octet-stream' })
  const href = window.URL.createObjectURL(blob)
  // 兼容 ie
  const link = document.createElement('a')
  link.style.display = 'none'
  link.href = href
  link.download = decodeURIComponent(filename)
  document.body.appendChild(link)
  link.click()
  document.body.removeChild(link)
  window.URL.revokeObjectURL(link)
}

对后端的文件接口做额外处理
一般文件流的接口后端会在请求上加一个fileName是转义后的中文
具体可以参考 Content-disposition
Content-disposition
前端需要在请求拦截器处理一下這个请求
注意fileName具体还要看后端怎么约定返回的再做处理(文件后缀)

request.interceptors.response.use(
  (resopnse) => {
  //判断一下响应头有没有這个属性表示是不是文件流
     if (Object.keys(response['headers']).includes('content-disposition')) {
            const fileName = response['headers']['content-disposition']
                .split(';')[1]
                .split('filename=')[1];
            const res = {
                fileName: decodeURIComponent(fileName),
                data: response.data,
            };
            return res;
        }
        return response.data;
  },
  (error) => {
    if (axios.isCancel(error)) {
      throw error.message
    } else if (error.resopnse) {
      let code = error.resopnse.status
      switch (code) {
        case 401:
          remoteCookies()
          window.location.href = window.location.href
          break
        case 502:
          Message.error(error.resopnse.message || '服务器错误')
      }
    } else {
      Message.error(error || '请求超时')
    }
    return Promise.reject()
  }
)

处理请求

	const getFile=async()=>{
	//结构拿到文件名称和data文件流
		let {fileName,data}=await getFileStream()
	//使用之前编写好的下载函数
	downLoad(fileName,data)
	}

为了避免实际开发中的联调问题,前端可以自己先模拟一下

现在用node方式返回一个文件流模拟下载
首先搭建基本项目工程
npm init 初始化一个package.json文件
下载 npm install express body-parser cors 几个工具包
在这里插入图片描述

Content-type对照表的网址
编写本地服务器

	var http = require('express')
	var app = http()
	var cors = require('cors')
	var body = require('body-parser')
	app.use(cors())
	const fs = require('fs') // 引入自带fs模块读取文件操作
	app.all('*',function(req,res,next){
		next()
	})
	app.use(body.urlencoded({extended:false}))
	app.use(body.json())
	app.get('/file',(req,res)=>{
	let fileName='./任务导入模板.xlsx'// 文件地址随意這里先写死
	let name=encodeURIComponent(fileName.split('.')[1])
	//设置文件流的响应头的俩种方法
		//res.setHeader()
		//res.writeHead()
		res.writeHead(200,{
			'Content-Type':'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
			'Content-Disposition':`attachment;filename=${name}.xlsx`,
			'Access-Control-Expose-Headers':'Content-Disposition'
		})
		//创建可读流
		let readStream=fs.createReadStream(fileName)
		readStream.on('data',(chunk)=>{}) //开始读取数据
		readStream.on('close',(res)=>{})//处理完成
		readStream.pipe(res) //  返回文件流
	})
	app.listen(8080,()=>{
		console.log('http://127.0.0.1:8080启动了')
	})

关于node文件相关的资料可以参考
奇舞精选的一篇文章
深入了解node的文件流
先用postman测试一下请求
在这里插入图片描述

看下前端页面请求
在这里插入图片描述
请求返回的文件流
在这里插入图片描述
在这里插入图片描述
控制台打印输出以及下载文件
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值