javascript
SpringBoot+ElementUI实现通用文件下载请求(全流程图文详细教程)
場景
在某些場景下需要前端瀏覽器從服務器端下載文件,比如需要下載導入Excel的模板。
?
注:
博客:
https://blog.csdn.net/badao_liumang_qizhi
關注公眾號
霸道的程序猿
獲取編程相關電子書、教程推送與免費下載。
實現
既然是實現通用下載接口,就要實現在后端配置一個下載文件的路徑,在前端進行下載請求時傳遞要下載的文件的名字,然后請求公共接口進行下載。
首先是在前端使用ElementUI的el-link添加一個下載鏈接
????????? <el-linktype="info"style="font-size:12px"@click="downloadTemplate('lxszTemplate.xlsx')">下載模板</el-link>這里設置了其點擊事件是調用downloadTemplate方法并傳遞一個文件名參數,這個文件名就是要下載的文件名。
然后在對應的點擊事件中
??? downloadTemplate(value) {download(value).then((response) => {}).catch((error) => {alert("錯誤:" + error);});},這里執行了一個download方法并傳遞文件名參數。
這個download方法是引用的第三方js中作為公共方法的。
引入方式
import { download } from "@/utils/badao";在utils下的badao.js中
// 通用下載方法 export function download(fileName) {window.location.href = baseURL + "/common/download?fileName=" + encodeURI(fileName) + "&delete=" + false; }將此方法進行暴露,作為公共方法。
在通用下載方法中使頁面跳轉window.location.href ,對應的url是SpringBoot中后臺的接口。
這里的baseURL是在badao.js中聲明的常量
const baseURL = process.env.VUE_APP_BASE_API對此常量的賦值是取得全局變量process的屬性,它對應的是在vue.config.js中配置的代理的地址
??? proxy: {[process.env.VUE_APP_BASE_API]: {target: `http://localhost:8080`,changeOrigin: true,pathRewrite: {['^' + process.env.VUE_APP_BASE_API]: ''}}},這里是我本地的8080端口。
然后在上面的通用的下載方法中在URL中還拼接了兩個參數
一個是文件名參數,調用的js的encodeURI方法可以將字符串作為URL進行編碼,一個是是否刪除的參數,默認是false,作為下載成功后是否將文件給刪除,即實現單次下載還是多次下載。
然后在這個url對應SprinBoot后臺接口方法中
??? @GetMapping("common/download")public void fileDownload(String fileName, Boolean delete, HttpServletResponse response, HttpServletRequest request) {try {if (!FileUtils.isValidFilename(fileName)) {throw new Exception(StringUtils.format("文件名稱({})非法,不允許下載。 ", fileName));}String realFileName = System.currentTimeMillis() + fileName.substring(fileName.indexOf("_") + 1);String filePath = RuoYiConfig.getDownloadPath() + fileName;response.setCharacterEncoding("utf-8");response.setContentType("multipart/form-data");response.setHeader("Content-Disposition","attachment;fileName=" + FileUtils.setFileDownloadHeader(request, realFileName));FileUtils.writeBytes(filePath, response.getOutputStream());if (delete) {FileUtils.deleteFile(filePath);}} catch (Exception e) {log.error("下載文件失敗", e);}}首先調用了文件處理工具類的驗證方法,驗證文件名稱是否合法。
這里是設置了指定文件名稱格式。
方法實現
??? public static boolean isValidFilename(String filename){return filename.matches(FILENAME_PATTERN);}其中參數為常量
public static String FILENAME_PATTERN = "[a-zA-Z0-9_\\-\\|\\.\\u4e00-\\u9fa5]+";下面是對服務器上文件路徑的獲取
String filePath = RuoYiConfig.getDownloadPath() + fileName;其中RuoyiConfig是配置類,用來讀取項目相關配置,即配置在application.yml中的內容。
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component;/*** 讀取項目相關配置** @author ruoyi*/ @Component @ConfigurationProperties(prefix = "ruoyi") public class RuoYiConfig {/** 項目名稱 */private String name;/** 版本 */private String version;/** 版權年份 */private String copyrightYear;/** 實例演示開關 */private boolean demoEnabled;/** 上傳路徑 */private static String profile;/** 獲取地址開關 */private static boolean addressEnabled;public String getName(){return name;}public void setName(String name){this.name = name;}public String getVersion(){return version;}public void setVersion(String version){this.version = version;}public String getCopyrightYear(){return copyrightYear;}public void setCopyrightYear(String copyrightYear){this.copyrightYear = copyrightYear;}public boolean isDemoEnabled(){return demoEnabled;}public void setDemoEnabled(boolean demoEnabled){this.demoEnabled = demoEnabled;}public static String getProfile(){return profile;}public void setProfile(String profile){RuoYiConfig.profile = profile;}public static boolean isAddressEnabled(){return addressEnabled;}public void setAddressEnabled(boolean addressEnabled){RuoYiConfig.addressEnabled = addressEnabled;}/*** 獲取頭像上傳路徑*/public static String getAvatarPath(){return getProfile() + "/avatar";}/*** 獲取下載路徑*/public static String getDownloadPath(){return getProfile() + "/download/";}/*** 獲取上傳路徑*/public static String getUploadPath(){return getProfile() + "/upload";} }這里的getDownloadPath就是獲取設置的下載路徑的方法,方法具體實現
??? public static String getDownloadPath(){return getProfile() + "/download/";}就是返回profile這個節點
??? public static String getProfile(){return profile;}因為使用了@ConfigurationProperties(prefix = "ruoyi")
所以在對應的application.yml中獲取profile就是獲取ruoyi下的profile的值
?
這里配置的路徑加上/download/再加上一個文件名就是服務器上要下載的模板文件的位置。
所以要提前將此文件放置在服務器上對應的位置。
這里服務器是我本地
?
然后對文件名進行一個添加時間戳的操作,防止多次下載重名問題。
然后設置響應編碼、響應頭、響應類型。
然后調用了文件工具類的輸出文件到Byte數組的方法writeBytes
方法實現
??? /*** 輸出指定文件的byte數組** @param filePath 文件路徑* @param os 輸出流* @return*/public static void writeBytes(String filePath, OutputStream os) throws IOException{FileInputStream fis = null;try{File file = new File(filePath);if (!file.exists()){throw new FileNotFoundException(filePath);}fis = new FileInputStream(file);byte[] b = new byte[1024];int length;while ((length = fis.read(b)) > 0){os.write(b, 0, length);}}catch (IOException e){throw e;}finally{if (os != null){try{os.close();}catch (IOException e1){e1.printStackTrace();}}if (fis != null){try{fis.close();}catch (IOException e1){e1.printStackTrace();}}}}以及下載文件名重新編碼的方法setFileDownloadHeader
方法實現
?
?? /*** 下載文件名重新編碼** @param request 請求對象* @param fileName 文件名* @return 編碼后的文件名*/public static String setFileDownloadHeader(HttpServletRequest request, String fileName)throws UnsupportedEncodingException{final String agent = request.getHeader("USER-AGENT");String filename = fileName;if (agent.contains("MSIE")){// IE瀏覽器filename = URLEncoder.encode(filename, "utf-8");filename = filename.replace("+", " ");}else if (agent.contains("Firefox")){// 火狐瀏覽器filename = new String(fileName.getBytes(), "ISO8859-1");}else if (agent.contains("Chrome")){// google瀏覽器filename = URLEncoder.encode(filename, "utf-8");}else{// 其它瀏覽器filename = URLEncoder.encode(filename, "utf-8");}return filename;}然后根據傳遞的參數是否刪除模板文件,執行刪除的工具類方法deleteFile
方法實現
??? /*** 刪除文件** @param filePath 文件* @return*/public static boolean deleteFile(String filePath){boolean flag = false;File file = new File(filePath);// 路徑為文件且不為空則進行刪除if (file.isFile() && file.exists()){file.delete();flag = true;}return flag;}完整的文件操作工具類代碼
package com.ruoyi.common.utils.file;import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.OutputStream; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import javax.servlet.http.HttpServletRequest;/*** 文件處理工具類** @author ruoyi*/ public class FileUtils {public static String FILENAME_PATTERN = "[a-zA-Z0-9_\\-\\|\\.\\u4e00-\\u9fa5]+";/*** 輸出指定文件的byte數組** @param filePath 文件路徑* @param os 輸出流* @return*/public static void writeBytes(String filePath, OutputStream os) throws IOException{FileInputStream fis = null;try{File file = new File(filePath);if (!file.exists()){throw new FileNotFoundException(filePath);}fis = new FileInputStream(file);byte[] b = new byte[1024];int length;while ((length = fis.read(b)) > 0){os.write(b, 0, length);}}catch (IOException e){throw e;}finally{if (os != null){try{os.close();}catch (IOException e1){e1.printStackTrace();}}if (fis != null){try{fis.close();}catch (IOException e1){e1.printStackTrace();}}}}/*** 刪除文件** @param filePath 文件* @return*/public static boolean deleteFile(String filePath){boolean flag = false;File file = new File(filePath);// 路徑為文件且不為空則進行刪除if (file.isFile() && file.exists()){file.delete();flag = true;}return flag;}/*** 文件名稱驗證** @param filename 文件名稱* @return true 正常 false 非法*/public static boolean isValidFilename(String filename){return filename.matches(FILENAME_PATTERN);}/*** 下載文件名重新編碼** @param request 請求對象* @param fileName 文件名* @return 編碼后的文件名*/public static String setFileDownloadHeader(HttpServletRequest request, String fileName)throws UnsupportedEncodingException{final String agent = request.getHeader("USER-AGENT");String filename = fileName;if (agent.contains("MSIE")){// IE瀏覽器filename = URLEncoder.encode(filename, "utf-8");filename = filename.replace("+", " ");}else if (agent.contains("Firefox")){// 火狐瀏覽器filename = new String(fileName.getBytes(), "ISO8859-1");}else if (agent.contains("Chrome")){// google瀏覽器filename = URLEncoder.encode(filename, "utf-8");}else{// 其它瀏覽器filename = URLEncoder.encode(filename, "utf-8");}return filename;} }?
?
總結
以上是生活随笔為你收集整理的SpringBoot+ElementUI实现通用文件下载请求(全流程图文详细教程)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java中将String格式的标准时间字
- 下一篇: MySql中怎样使用case-when实