Preparation: Import the maven jar package
<dependency> <groupId>org.webjars.npm</groupId> <artifactId>axios</artifactId> <version>1.5.1</version> </dependency>
Step 1: Write the front-end page
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Download Center</title> <style> .txt { color: green; } </style> </head> <body> <div id="app"> <h1>Download Center</h1> <ol> <li><span class="txt">WeChat Mini Program Project</span> <a href="javascript:void(0)" onclick="sendDownloadAsync('WeChat Mini Program Project.zip','d5cbcd2a-7e08-11ee-bf9c -54e1ad104b87')">Download</a></li> <li><span class="txt">Java Engineer Resume Template</span> <a href="javascript:;" onclick="sendDownloadAsync('Java Engineer Resume Template.docx','cbae974f-7e08-11ee-bf9c-54e1ad104b87' )">Download</a></li> </ol> </div> <script src="/webjars/axios/1.5.1/dist/axios.js"></script> <script> // Function: Download file function fileDownload(res) { //headers:"attachment;filename=WeChat Mini Program Project.zip" //Indicates getting the file name from the response header const fileName = decodeURI(res.headers['content-disposition']).replace(/\w + ;filename=(.*)/, '$1') console.log("The parsed file name is ",fileName) //const blob = new Blob([data], {type: headers['content-type']}) const blob = new Blob([res.data], { type: "application/octet-stream"}); const fileUrl = window.URL.createObjectURL(blob) let link = document.createElement('a') //Create an a tag element link.href = fileUrl //Set the href attribute of the a tag link.download = decodeURI(fileName) //Set the downloaded file name link.style.display = 'none' //Set to not display document.body.appendChild(link) //Add the a tag element to the page link.click() //Automatically trigger click event document.body.removeChild(link);//Remove element after download is complete window.URL.revokeObjectURL(fileUrl); // Release the blob object } // Function: Initiate an asynchronous file download request function sendDownloadAsync(fileName,apiKey){ axios({ method: 'POST', url: '/api/download/file', data: { fileName, apiKey }, headers: { //"Authorization": localStorage.getItem("token") "Content-Type": "application/x-www-form-urlencoded" }, responseType: 'blob' }).then(res => { const data = res.data; const fileReader = new FileReader(); // Carry out object replacement to avoid downloading the error message returned by the back-end interface as a file. fileReader.onload = (event) => { try { const data = JSON.parse(event.target.result); if (data.code !== 0) { // Failed to parse into an object, indicating that it is ordinary object data console.log(`Download prompt: ${data.msg}`); alert(`Download prompt: ${data.msg}`) } } catch (err) { // Failed to parse into an object, indicating that it is a normal file stream and can be downloaded //Download file normally fileDownload(res) } }; fileReader.readAsText(data); }) } </script> </body> </html>
Step 2: Write the download controller
@RestController @RequestMapping("/api/download") public class DownloadController { @Autowired private UploadProperties uploadProperties; // Redis private static final List<String> APIKEY_LIST = new ArrayList<>( Arrays.asList( "d5cbcd2a-7e08-11ee-bf9c-54e1ad104b87", "cbae974f-7e08-11ee-bf9c-54e1ad104b87" ) ); /** * download file * * @param fileName Download file name * @param apiKey apiKey */ @PostMapping("/file") public void downloadFile(@RequestParam("fileName") String fileName, @RequestParam("apiKey") String apiKey, HttpServletResponse response) throws UnsupportedEncodingException, FileNotFoundException, BizException { final String savePath = uploadProperties.getSavePath(); if (StringUtils.isBlank(fileName)) { throw new BizException(400, "The downloaded file cannot be empty!"); } if (StringUtils.isBlank(apiKey)) { throw new BizException(400, "apiKey cannot be empty!"); } if (!APIKEY_LIST.contains(apiKey)) { throw new BizException(400, "apiKey is invalid, file downloading is prohibited!"); } File downloadFile = new File(savePath, fileName); if (!downloadFile.exists()) { throw new BizException(400, "The file to be downloaded was not found!"); } File path = new File(ResourceUtils.getURL("classpath:").getPath()); System.out.println("path?>?>>>>>>>>>>>>>>>>>>>>>>>>" + path); response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, StandardCharsets.UTF_8.name())); response.setContentType("application/octet-stream"); response.addHeader("Content-Length", downloadFile.length() + ""); // Disable browser caching /* Cache-Control: no-cache, no-store, must-revalidate Pragma: no-cache Expires: 0 Among them, Cache-Control is used for HTTP1.1 (including 1.1) and above; Pragma is used for HTTP1.0; Expires is used for proxy server caching. */ response.addHeader("Cache-Control", "no-cache, no-store, must-revalidate"); response.addHeader("Pragma", "no-cache"); response.addHeader("Expires", "0"); byte[] buffer = new byte[8 * 1024]; // 8kb int readBytes = 0; try ( BufferedInputStream bis = new BufferedInputStream(new FileInputStream(downloadFile)); BufferedOutputStream bos = new BufferedOutputStream(response.getOutputStream()); ) { while ((readBytes = bis.read(buffer)) != -1) { bos.write(buffer, 0, readBytes); bos.flush(); } response.flushBuffer(); APIKEY_LIST.remove(apiKey); } catch (Exception ex) { throw new BizException(500, "File download failed"); } } }
Step 3: Unify JSON results
@ApiModel("Unified response result") public class CommonResult<T> { @ApiModelProperty("Response status code") private int code; @ApiModelProperty("Response prompt information") private String msg; @ApiModelProperty("Response data") private T data; public CommonResult(int code, String msg) { this.code = code; this.msg = msg; } public CommonResult(ResultCode resultCode) { this.code = resultCode.getCode(); this.msg = resultCode.getMsg(); } public CommonResult(int code, String msg, T data) { this.code = code; this.msg = msg; this.data = data; } public static <T> CommonResult<T> success(T data) { return new CommonResult<T>(ResultCode.SUCCESS.getCode(), ResultCode.SUCCESS.getMsg(), data); } public static <T> CommonResult<T> success(String msg) { return new CommonResult<T>(0,msg); } public static <T> CommonResult<T> fail(ResultCode resultCode) { return new CommonResult<T>(resultCode.getCode(), resultCode.getMsg()); } public static <T> CommonResult<T> fail(int code, String msg) { return new CommonResult<T>(code,msg); } public static <T> CommonResult<T> error() { return new CommonResult<T>(ResultCode.SYSTEM_ERROR); } public static <T> CommonResult<T> error(int code,String msg) { return new CommonResult<T>(code,msg); } public int getCode() { return code; } public void setCode(int code) { this.code = code; } public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } public T getData() { return data; } public void setData(T data) { this.data = data; } }
Step 3: Unify JSON results: write enumeration class to return code and msg
public enum ResultCode { SUCCESS(0, "Operation successful"), FAILURE(1,"Operation failed"), PARAM_VALID_ERROR(400, "Parameter verification error"), UNAUTHORIZED(401, "Uncertified"), FORBIDDEN(403, "No permission"), SYSTEM_ERROR(500, "The system is busy, please try again later!") ; private int code; private String msg; ResultCode(int code, String msg) { this.code = code; this.msg = msg; } public int getCode() { return code; } public String getMsg() { return msg; } }
Step 4: Global exception handler
public class BizException extends Exception{ private int code; private String message; public BizException(ResultCode resultCode) { super(resultCode.getMsg()); this.code = resultCode.getCode(); this.message = resultCode.getMsg(); } public BizException(int code,String message) { super(message); this.code = code; this.message = message; } public BizException(int code,String message, Throwable cause) { super(message, cause); this.code = code; this.message = message; } public int getCode() { return code; } @Override public String getMessage() { return message; } }
/** * Global exception handler */ @RestControllerAdvice //@ControllerAdvice //@ResponseBody @Slf4j public class GlobalExceptionHandler { /** * Handle missing request parameter exception * @param ex HttpMessageNotReadableException * @return */ @ExceptionHandler(MissingServletRequestParameterException.class) @ResponseStatus(value = HttpStatus.BAD_REQUEST) public CommonResult handleMissingException( MissingServletRequestParameterException ex) { log.error("Missing request parameters, {}", ex.getMessage()); return new CommonResult(400, "Missing necessary request parameters"); } /** * Handle missing request parameter exception * @param ex HttpMessageNotReadableException * @return */ @ExceptionHandler(MaxUploadSizeExceededException.class) @ResponseStatus(value = HttpStatus.BAD_REQUEST) public CommonResult handleUploadSizeException( MaxUploadSizeExceededException ex) { log.error("The maximum allowed file upload size exceeds {} bytes.,", ex.getMaxUploadSize()); return new CommonResult(400, "The uploaded file size exceeds" + ex.getMaxUploadSize() + "B"); } /** * Handle request parameter verification exceptions */ @ExceptionHandler(value = MethodArgumentNotValidException.class) public CommonResult handleBindException(MethodArgumentNotValidException ex){ log.error("There is a problem with request parameter verification: {}, exception type: {}", ex.getMessage(), ex.getClass()); // for debug String message = ex.getBindingResult().getFieldError().getDefaultMessage(); return CommonResult.error(400,message); } /** * Handle customized business exceptions */ @ExceptionHandler(value = BizException.class) public CommonResult handleBizException(BizException ex){ log.error("Business operation problem: {}, exception type: {}", ex.getMessage(), ex.getClass()); // for debug return CommonResult.error(ex.getCode(),ex.getMessage()); } /** * Handle system exceptions */ @ExceptionHandler(value = Exception.class) public CommonResult handleException(Exception ex){ log.error("System problem: {}, exception type: {}", ex.getMessage(), ex.getClass()); // for debug return CommonResult.error(); } }
The knowledge points of the article match the official knowledge files, and you can further learn relevant knowledge. Cloud native entry-level skills treeHomepageOverview 16993 people are learning the system