做网站如何避免商标侵权,视频网站dedecms,免费网站建设优化,跨境电商选品平台01 背景
在后端开发中#xff0c;通常会有文件下载的需求#xff0c;常用的解决方案有两种#xff1a;
不通过后端应用#xff0c;直接使用nginx直接转发文件地址下载#xff08;适用于一些公开的文件#xff0c;因为这里不需要授权#xff09;通过后端进行下载#…01 背景
在后端开发中通常会有文件下载的需求常用的解决方案有两种
不通过后端应用直接使用nginx直接转发文件地址下载适用于一些公开的文件因为这里不需要授权通过后端进行下载同时进行一些业务处理
本篇主要以方法2进行介绍方法2的原理步骤如下
读取文件得到文件的字节流将字节流写入到响应输出流中
02 一次性读取到内存通过响应输出流输出到前端 GetMapping(/file/download)public void fileDownload(HttpServletResponse response, RequestParam(filePath) String filePath) {File file new File(filePath);if (!file.exists()) {throw new BusinessException(当前下载的文件不存在请检查路径是否正确);}// 将文件写入输入流try (InputStream is new BufferedInputStream(Files.newInputStream(file.toPath()))) {// 一次性读取到内存中byte[] buffer new byte[is.available()];int read is.read(buffer);// 清空 responseresponse.reset();response.setCharacterEncoding(UTF-8);// Content-Disposition的作用告知浏览器以何种方式显示响应返回的文件用浏览器打开还是以附件的形式下载到本地保存// attachment表示以附件方式下载 inline表示在线打开 Content-Disposition: inline; filename文件名.mp3// filename表示文件的默认名称因为网络传输只支持URL编码的相关支付因此需要将文件名URL编码后进行传输,前端收到后需要反编码才能获取到真正的名称response.addHeader(Content-Disposition, attachment;filename URLEncoder.encode(file.getName(), UTF-8));// 告知浏览器文件的大小response.addHeader(Content-Length, file.length());OutputStream outputStream new BufferedOutputStream(response.getOutputStream());response.setContentType(application/octet-stream);outputStream.write(buffer);outputStream.flush();outputStream.close();} catch (IOException e) {throw new RuntimeException(e);}}适用于小文件如果文件过大一次性读取到内存中可能会出现oom的问题 02 将文件流通过循环写入到响应输出流中推荐 GetMapping(/file/download)public void fileDownload(HttpServletResponse response, RequestParam(filePath) String filePath) {File file new File(filePath);if (!file.exists()) {throw new BusinessException(当前下载的文件不存在请检查路径是否正确);}// 清空 responseresponse.reset();response.setCharacterEncoding(UTF-8);response.addHeader(Content-Disposition, attachment;filename URLEncoder.encode(file.getName(), UTF-8));response.setContentType(application/octet-stream);// 将文件读到输入流中try (InputStream is new BufferedInputStream(Files.newInputStream(file.toPath()))) {OutputStream outputStream new BufferedOutputStream(response.getOutputStream());byte[] buffer new byte[1024];int len;//从输入流中读取一定数量的字节并将其存储在缓冲区字节数组中读到末尾返回-1while((len is.read(buffer)) 0){outputStream.write(buffer, 0, len);}outputStream.close();} catch (IOException e) {throw new RuntimeException(e);}}03 从网络上获取文件并返回给前端 GetMapping(/net/download)public void netDownload(HttpServletResponse response, RequestParam(fileAddress) String fileAddress, RequestParam(filename) String filename) {try {URL url new URL(fileAddress);URLConnection conn url.openConnection();InputStream inputStream conn.getInputStream();response.reset();response.setContentType(conn.getContentType());response.setHeader(Content-Disposition, attachment; filename URLEncoder.encode(filename, UTF-8));byte[] buffer new byte[1024];int len;OutputStream outputStream response.getOutputStream();while ((len inputStream.read(buffer)) 0) {outputStream.write(buffer, 0, len);}inputStream.close();} catch (IOException e) {throw new RuntimeException(e);}}04 从网络上获取文本并下载到本地 GetMapping(/netDownloadLocal)public void downloadNet(RequestParam(netAddress) String netAddress, RequestParam(filepath) String filepath) {try {URL url new URL(netAddress);URLConnection conn url.openConnection();InputStream inputStream conn.getInputStream();FileOutputStream fileOutputStream new FileOutputStream(filepath);int byteread;byte[] buffer new byte[1024];while ((byteread inputStream.read(buffer)) ! -1) {fileOutputStream.write(buffer, 0, byteread);}fileOutputStream.close();} catch (IOException e) {throw new RuntimeException(e);}}05 总结
一定要搞清楚InputStream和OutputStream的区别如果搞不清楚的可以和字符流进行映射InputStream - Reader,OutPutStream - Writer换成这样你就知道读取内容需要使用Reader写入需要使用Writer了。
返回给前端的是输出流不需要你显示的去返回return response;这样会报错