最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

JS二進(jìn)制流文件下載導(dǎo)出(接口返回二進(jìn)制流)亂碼處理方法

 更新時(shí)間:2023年12月20日 11:20:37   作者:hzxOnlineOk  
這篇文章主要介紹了JS二進(jìn)制流文件下載導(dǎo)出(接口返回二進(jìn)制流)亂碼處理方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧

給下載文件起名字有兩種方式:

  • 固定值+時(shí)間戳(一般都加上時(shí)間戳)
  • 后端將文件名放到response的headers中返回,我們?nèi)≈诞?dāng)做文件名

 使用react的同學(xué)注意了,fetch難設(shè)置亂碼轉(zhuǎn)碼,建議使用axios,用fetch親自嘗試失敗+10086次,下載下來(lái)的xlsx全是亂碼

平時(shí)在前端下載文件有兩種方式,一種是后臺(tái)提供一個(gè) 下載的http URL,然后用 window.open(URL)或者創(chuàng)建一個(gè)a標(biāo)簽的href屬性下載,另一種就是后臺(tái)直接返回文件的二進(jìn)制內(nèi)容,然后前端轉(zhuǎn)化一下再下載。

由于第一種方式比較簡(jiǎn)單,在此不做探討。本文主要講解一下第二種方式怎么實(shí)現(xiàn)。

Blob、ajax(axios)
mdn 上是這樣介紹 Blob 的:

Blob 對(duì)象表示一個(gè)不可變、原始數(shù)據(jù)的類文件對(duì)象。Blob 表示的不一定是JavaScript原生格式的數(shù)據(jù)

具體使用方法

axios({
  method: 'post',
  url: '/export',
})
.then(res => {
  // 假設(shè) data 是返回來(lái)的二進(jìn)制數(shù)據(jù)
  const data = res.data
  const url = window.URL.createObjectURL(new Blob([data], {type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"}))
  const link = document.createElement('a')
  link.style.display = 'none'
  link.href = url
  link.setAttribute('download', 'excel.xlsx')
  document.body.appendChild(link)
  link.click()
  document.body.removeChild(link)
})

打開下載的文件,看看結(jié)果是否正確。

一堆亂碼…

一定有哪里不對(duì)。

最后發(fā)現(xiàn)是參數(shù) responseType 的問(wèn)題,responseType 它表示服務(wù)器響應(yīng)的數(shù)據(jù)類型,由于后臺(tái)返回來(lái)的是二進(jìn)制數(shù)據(jù),所以我們要把它設(shè)為 arraybuffer(如果后端傳遞過(guò)來(lái)約定的是blob,那么responseType應(yīng)該設(shè)置成這個(gè)responseType: 'blob')
接下來(lái)再看看結(jié)果是否正確。

axios({
  method: 'post',
  url: '/export',
  responseType: 'arraybuffer',
  // responseType: 'blob'
})
.then(res => {
  // 假設(shè) data 是返回來(lái)的二進(jìn)制數(shù)據(jù)
  const data = res.data
  const url = window.URL.createObjectURL(new Blob([data], {type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"}))
  const link = document.createElement('a')
  link.style.display = 'none'
  link.href = url
  link.setAttribute('download', 'excel.xlsx')
  document.body.appendChild(link)
  link.click()
  document.body.removeChild(link)
})

這次沒有問(wèn)題,文件能正常打開,內(nèi)容也是正常的,不再是亂碼。

根據(jù)后臺(tái)接口內(nèi)容決定是否下載文件
作者的項(xiàng)目有大量的頁(yè)面都有下載文件的需求,而且這個(gè)需求還有點(diǎn)變態(tài)。

具體需求如下

如果下載文件的數(shù)據(jù)量條數(shù)符合要求,正常下載(每個(gè)頁(yè)面限制下載數(shù)據(jù)量是不一樣的,所以不能在前端寫死)。
如果文件過(guò)大,后臺(tái)返回 { code: 199999, msg: '文件過(guò)大,請(qǐng)重新設(shè)置查詢項(xiàng)', data: null },然后前端再進(jìn)行報(bào)錯(cuò)提示。
先來(lái)分析一下,首先根據(jù)上文,我們都知道下載文件的接口響應(yīng)數(shù)據(jù)類型為 arraybuffer。返回的數(shù)據(jù)無(wú)論是二進(jìn)制文件,還是 JSON 字符串,前端接收到的其實(shí)都是 arraybuffer。所以我們要對(duì) arraybuffer 的內(nèi)容作個(gè)判斷,在接收到數(shù)據(jù)時(shí)將它轉(zhuǎn)換為字符串,判斷是否有 code: 199999。如果有,則報(bào)錯(cuò)提示,如果沒有,則是正常文件,下載即可。具體實(shí)現(xiàn)如下:

axios.interceptors.response.use(response => {
    const res = response.data
    // 判斷響應(yīng)數(shù)據(jù)類型是否 ArrayBuffer,true 則是下載文件接口,false 則是正常接口
    if (res instanceof ArrayBuffer) {
        const utf8decoder = new TextDecoder()
        const u8arr = new Uint8Array(res)
        // 將二進(jìn)制數(shù)據(jù)轉(zhuǎn)為字符串
        const temp = utf8decoder.decode(u8arr)
        if (temp.includes('{code:199999')) {
            Message({
                // 字符串轉(zhuǎn)為 JSON 對(duì)象
                message: JSON.parse(temp).msg,
                type: 'error',
                duration: 5000,
            })
            return Promise.reject()
        }
    }
    // 正常類型接口,省略代碼...
    return res
}, (error) => {
    // 省略代碼...
    return Promise.reject(error)
})

react fetch(react方案)

const qryurl = `/offapi/liveaum/exportExcelData`;
    fetch(qryurl, {
      method: 'POST',
      credentials: 'include',
      headers: { Accept: 'application/json', 'Content-Type': 'application/json;charset=UTF-8' },
      body: JSON.stringify(params),
    }).then(response => {
      if (response.ok) {
        let downloadFileName = decodeURIComponent(response.headers.get('filename'));
        this.setState({ downloadFileName, downModalShow: true, iconLoading: false });
        response.blob().then(blob => {
          downBlob = blob;
        });
      }
    }).catch(function(err) {
      console.log(err);
      downBlob = null;
      message.warning('暫未查詢到數(shù)據(jù)');
      this.setState({ iconLoading: false })
    });
// 導(dǎo)出文件
  handleOk = () => {
    const link = document.createElement('a');
    link.style.display = 'none';
    link.href = URL.createObjectURL(downBlob);
    link.download = `${this.state.downloadFileName}.xls`;
    document.body.appendChild(link);
    link.click();
    URL.revokeObjectURL(link.href);
    document.body.removeChild(link);
    message.success('下載成功');
    this.onModalclose();
  };

到此這篇關(guān)于JS二進(jìn)制流文件下載導(dǎo)出(接口返回二進(jìn)制流)亂碼處理的文章就介紹到這了,更多相關(guān)js二進(jìn)制文件下載導(dǎo)出內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 判斷js數(shù)據(jù)類型的函數(shù)實(shí)例詳解

    判斷js數(shù)據(jù)類型的函數(shù)實(shí)例詳解

    這篇文章主要介紹了一個(gè)判斷js數(shù)據(jù)類型的函數(shù),本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2019-05-05
  • JavaScript Event學(xué)習(xí)第九章 鼠標(biāo)事件

    JavaScript Event學(xué)習(xí)第九章 鼠標(biāo)事件

    鼠標(biāo)事件是到目前為止最重要的事件。在這一章我將介紹一些鼠標(biāo)事件的最常見的問(wèn)題和技巧。
    2010-02-02
  • JavaScript繼承的特性與實(shí)踐應(yīng)用深入詳解

    JavaScript繼承的特性與實(shí)踐應(yīng)用深入詳解

    這篇文章主要介紹了JavaScript繼承的特性與實(shí)踐應(yīng)用,結(jié)合實(shí)例形式較為深入的分析了javascript繼承相關(guān)概念、特性、原理、用法及操作注意事項(xiàng),需要的朋友可以參考下
    2018-12-12
  • trim原型函數(shù)看js正則表達(dá)式的性能

    trim原型函數(shù)看js正則表達(dá)式的性能

    如果你看到別人寫trim函數(shù)是用循環(huán)而不用正則表達(dá)式來(lái)寫,請(qǐng)不要取笑,也許,他們就是高手。如果你很自信你的trim函數(shù)效率很高,請(qǐng)看完本文再下結(jié)論。
    2008-12-12
  • 基于BootstrapValidator的Form表單驗(yàn)證(24)

    基于BootstrapValidator的Form表單驗(yàn)證(24)

    這篇文章主要為大家詳細(xì)介紹了基于BootstrapValidator的Form表驗(yàn)證,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-12-12
  • layui實(shí)現(xiàn)table加載的示例代碼

    layui實(shí)現(xiàn)table加載的示例代碼

    今天小編就為大家分享一篇layui實(shí)現(xiàn)table加載的示例代碼,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2018-08-08
  • 開啟BootStrap學(xué)習(xí)之旅

    開啟BootStrap學(xué)習(xí)之旅

    當(dāng)下最流行的前端開發(fā)框架Bootstrap,可大大簡(jiǎn)化網(wǎng)站開發(fā)過(guò)程,從而深受廣大開發(fā)者的喜歡,你如果也喜歡Bootstrap前端開發(fā)框架,不要錯(cuò)過(guò)這次旅行
    2016-05-05
  • js實(shí)現(xiàn)彈框效果

    js實(shí)現(xiàn)彈框效果

    這篇文章主要為大家詳細(xì)介紹了js實(shí)現(xiàn)彈框效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-03-03
  • 詳解JS中???和?.?和||的區(qū)別

    詳解JS中???和?.?和||的區(qū)別

    這篇文章主要介紹了詳解JS中???和?.?和||的區(qū)別,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-06-06
  • 超鏈接怎么正確調(diào)用javascript函數(shù)

    超鏈接怎么正確調(diào)用javascript函數(shù)

    本文介紹使用超鏈接調(diào)用javasript函數(shù)且不會(huì)影響GIF圖片動(dòng)畫的方法,有遇到相同問(wèn)題的小伙伴可以參考一下。
    2016-05-05

最新評(píng)論

敦化市| 武鸣县| 巴东县| 清涧县| 奉贤区| 五华县| 霍林郭勒市| 宁陕县| 永登县| 甘肃省| 收藏| 新泰市| 潞城市| 大庆市| 绥德县| 西青区| 内丘县| 临安市| 临汾市| 白银市| 辽宁省| 潞西市| 灵宝市| 东阿县| 苍溪县| 禹州市| 石首市| 玉田县| 怀集县| 古丈县| 二连浩特市| 常宁市| 建瓯市| 城步| 石首市| 土默特左旗| 清水县| 定兴县| 东至县| 象州县| 嘉兴市|