前端无插件导出excel csv txt 文件

项目背景 : react + ant
需导出三种格式 excel csv txt
注 : 我没有用插件 , 用的是浏览器的下载功能

其中 excel 后台返回了blob文件流格式 , 其他是正常格式

故 需单独处理 

       const Blobs = new Blob([res.data]);
        if (format.includes('xlsx')) {
          fileName = res.fileName.split('filename=')[1] || Date.now() + '.xlsx';
        } else if (format.includes('csv')) {
          fileName = Date.now() + '.csv';
        } else if (format.includes('txt')) {
          fileName = Date.now() + '.txt';
        }

        const url = window.URL.createObjectURL(Blobs);
        const link = document.createElement('a');
        link.style.display = 'none';
        link.href = url;
        link.setAttribute('download', fileName);
        document.body.appendChild(link);
        link.click();
        document.body.removeChild(link);
        window.URL.revokeObjectURL(link.href);

1. 需在响应拦截器中做单独处理文件流下载 (否则会出现csv txt等格式可以下载 , 而文件流的excel格式无法下载也不报错)

我们可以在响应拦截器中log一下 , 其实我们只需要response.data和响应标头中的filename




故导出整体代码如下

// 响应拦截器  (这样即可)
axios.interceptors.response.use(
  (response) => {
     console.log('响应拦截器的response', response);

    if (response.request.responseType === 'blob') {
      return Promise.resolve({
        data: response.data,
        fileName: response.headers['content-disposition'] || '',
      });
    }
    return Promise.resolve(response);
  },
  (error) => {
    console.log(error);
      return Promise.reject(error);
  },
);




---------------------------------------------------

在发请求的js中添加标识

// 导出用户
const getDerive = async (obj) => {
  try {
    const res = await axios.post('/api/v1/help/export', obj, {
      responseType: 'blob',
    });
    const code = get(res, 'data.code', 0);
    const data = get(res, 'data.data', []);
    const msg = get(res, 'data.message', '数据获取失败!');
    if (code === 200) {
      return data;
    } else {
      return res;
    }
  } catch (error) {
    return false;
  }
};


----------------------------------------------------

在jsx中 进行导出操作

     const Blobs = new Blob([res.data]);
        if (format.includes('xlsx')) {
          fileName = res.fileName.split('filename=')[1] || Date.now() + '.xlsx';
        } else if (format.includes('csv')) {
          fileName = Date.now() + '.csv';
        } else if (format.includes('txt')) {
          fileName = Date.now() + '.txt';
        }

        const url = window.URL.createObjectURL(Blobs);
        const link = document.createElement('a');
        link.style.display = 'none';
        link.href = url;
        link.setAttribute('download', fileName);
        document.body.appendChild(link);
        link.click();
        document.body.removeChild(link);
        window.URL.revokeObjectURL(link.href);


拓 : react的一个小坑点 , 用ant-menu实现导出时选中不同格式

需实现效果如下 : 可以连续选中excel格式或者其他格式



问题就是 : 选择完excel格式后再选excel不能选中了, 只能选其他格式 , 起初我以为是组件没销毁



后来发现不是菜单组件没销毁 , 而是setState操作通常是异步的 , 当我设置setFormat('csv')时它没监听到 , 虽然ref也是异步操作 , 但ref.current 属性可以被修改而不会引发组件的重新渲染 , 可以直接拿到想要的值

解决如下

 

// 旧代码如下
 
 const [format, setFormat] = useState('');

 const formatCounter = useRef(0); // 设置一个字符串为了点击下拉菜单
 
<Dropdown
                  menu={{
                    items: [
                      {
                        label: (
                          <a
                            onClick={() => {
                              setFormat(`xlsx`);  // 旧代码

                              setFormat(`xlsx${formatCounter.current}`);  // 这样就可以了
                              formatCounter.current++;
                            }}
                          >
                            {t('derive3')}
                          </a>
                        ),
                        key: '1',
                      },
                      {
                        label: (
                          <a
                            onClick={() => {
                              setFormat(`csv`);  // 旧代码

                              setFormat(`csv${formatCounter.current}`);  // 这样就可以了
                              formatCounter.current++;
                            }}
                          >
                            {t('derive4')}
                          </a>
                        ),
                        key: '2',
                      },
                      {
                        label: (
                          <a
                            onClick={() => {
                              setFormat(`txt`);  // 旧代码

                              setFormat(`txt${formatCounter.current}`);  // 这样就可以了
                              formatCounter.current++;
                            }}
                          >
                            {t('derive5')}
                          </a>
                        ),
                        key: '3',
                      },
                    ],
                  }}
                >


// 点击弹出导出弹窗
  useEffect(() => {
    if (format) {
      setDeriveModal(true);
    }
  }, [format]);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值