天天看點

導出功能的體驗沒做好,差點被投訴了

背景:

新上線的一個功能,大家都做得比較辛苦。

同時,也收到使用者回報功能不好用。

問題描述:

回報的問題是,在導出的檔案名看不懂,一旦導出多了,不好找。如果下載下傳一個使用者再自己重新命名一下,又會影響效率。

導出功能的體驗沒做好,差點被投訴了

根據檔案名不知道裡面的内容

這就很煩了,

不改下名,不好找導出的檔案。

改吧,又太麻煩。

使用者又能拿這個功能怎麼樣,隻能吐槽這個新功能不好用罷了

這是一個非功能的體驗問題。

直接原因:

沒有指定下載下傳檔案名,浏覽器使用了預設的命名政策:将url上的非法字元去掉,然後拼一下。如果得到的字元串太長,還會進行截斷處理。

原因分析:

使用者執行導出後,後端傳回的是一個包含了導出内容的oss位址,也就是一個Url。前端直接把這個url放到<a>标簽中。使用者點選進行下載下傳

導出功能的體驗沒做好,差點被投訴了

下載下傳時的互動

這種情況下,浏覽器下載下傳時展示在狀态欄上的名字,浏覽器就自由發揮了,目前浏覽器的命名規則是将url上的非法字元去掉,然後拼一下。

導出功能的體驗沒做好,差點被投訴了

下載下傳的檔案名

優化意見:

方案1:伺服器傳回導出内容的二進制流。由伺服器指定浏覽器導出的檔案名。

代碼實作:

/**
 * 将二進制流寫入HttpServletResponse
 *
 * @param fileName 浏覽器下載下傳時彈出下載下傳框、展示在狀态欄中的檔案名
 * @param response 承載傳回給浏覽器的對象
 * @param workbook POI中定義的excel。承載了excel模型及存放的資料
 * @throws IOException
 */
private static void downLoadExcelWithOutputStream(HttpServletResponse response, Workbook workbook, String fileName) throws IOException {
    response.setCharacterEncoding(StandardCharsets.UTF_8.name());
    response.setHeader("content-Type", "application/vnd.ms-excel");
    /**
     * 如果檔案名是包含中文字元,需要進行編碼。否則,浏覽器下載下傳時檔案名會是亂碼
     */
    response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, StandardCharsets.UTF_8.name()));
    ServletOutputStream servletOutputStream = response.getOutputStream();
    workbook.write(servletOutputStream);
     /**
     * 關閉writer,釋放記憶體
     */ 
    workbook.close();
    servletOutputStream.flush();
    /**
     * 此處記得關閉輸出Servlet流
     */
    IoUtil.close(servletOutputStream);
}           
導出功能的體驗沒做好,差點被投訴了

關鍵代碼

方案2:伺服器傳回存放下載下傳檔案的oss Url,前端指定浏覽器下載下傳檔案的檔案名。

<!DOCTYPE html>

<html>

<head>

<meta charset="utf-8">

<title>前端自定義下載下傳檔案名e</title>

</head>

<body>

待下載下傳的檔案:<input type="text" name="fileUrl" id="fileUrl" value='' ><br />

自定義檔案名:<input type="text" name="fileName" id="fileName" value=''><br/>

<button id='btn'>下載下傳</button><br />

<span id='status'></span><br />

</body>

<script>

var url=document.getElementById('fileUrl').value;

console.log(url);

document.getElementById('btn').onclick = function() {

document.getElementById('status').innerHTML = '下載下傳中';

fetch(url).then(res => res.blob().then(blob => {

var a = document.createElement('a');

var url = window.URL.createObjectURL(blob);

a.href = url;

a.download = document.getElementById('fileName').value;

a.click();

window.URL.revokeObjectURL(url);

document.getElementById('status').innerHTML = '下載下傳完成';

}));

};

</script>

</html>

導出功能的體驗沒做好,差點被投訴了

把oss檔案以blob的方式下載下傳到目前頁,然後再建立a标簽

效果:

導出功能的體驗沒做好,差點被投訴了

使用

确定優化方案

最終標明了方案2。

原因是方案2改動最小,可以快速響應及時解決使用者關心的問題。

思考

方案1:

優點:

  1. 可以由後端靈活自定義浏覽器下載下傳時的檔案名。沒有相容性問題
  2. 代碼實作簡單。代碼量少,實作簡單

缺點:

  1. 伺服器帶寬打滿後會影響其它功能的使用。伺服器寫資料到浏覽器會占用伺服器網卡的總帶寬,如果打滿,其它功能也用不了。可以把帶寬想象成一座橋,大檔案就像一個大卡車。
  2. 影響到伺服器的穩定性。大檔案生成及傳輸過程會持續占用伺服器記憶體。伺服器的記憶體是有限的,下載下傳大檔案的功能占用了,其它功能就不能正常工作了。
  3. 分布式環境中,增加了代碼的複雜度。Feign或RestTempate在處理位元組流時需要特殊的配置,在更新這些http客戶元件時,也需要驗證對這些已有功能的影響。

方案2:

繼續閱讀