方案一:
// 文件下载 @RequestMapping(value = "/downloadFile") public ResponseEntity<byte[]> downloadFile() throws IOException { String basePath = "F:/testDir/"; String fileName = "ChromeStandaloneV45.0.2454.101.exe"; HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_OCTET_STREAM); headers.setContentDispositionFormData("attachment", URLEncoder.encode(fileName, "utf-8"));//这里用URLEncoder.encode是为了解决文件名中的中文乱码问题 return new ResponseEntity<byte[]>(FileUtils.readFileToByteArray(new File(basePath + fileName)), headers, HttpStatus.CREATED); }
配置xxx-servelt.xml
<bean id="stringHttpMessageConverter" class="org.springframework.http.converter.StringHttpMessageConverter"> <constructor-arg value="UTF-8" index="0"></constructor-arg><!-- 避免出现乱码 --> <property name="supportedMediaTypes"> <list> <value>text/plain;charset=UTF-8</value> </list> </property> </bean> <!-- 避免IE出现下载JSON文件的情况 --> <bean id="mappingJacksonHttpMessageConverter" class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"> <property name="supportedMediaTypes"> <list> <value>text/html;charset=UTF-8</value> </list> </property> </bean> <bean id="byteArrayHttpMessageConverter" class="org.springframework.http.converter.ByteArrayHttpMessageConverter" /> <!-- 启动Spring MVC的注解功能,完成请求和注解POJO的映射 --> <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"> <property name="messageConverters"> <list> <ref bean="byteArrayHttpMessageConverter" /> <ref bean="stringHttpMessageConverter" /> <ref bean="mappingJacksonHttpMessageConverter" /><!-- json转换器 --> </list> </property> </bean>
方案二:通过Response获得输出流,以流的形式下载文件。以下代码大部分是一样的,自行选择
/** * 文件下载 * * @param path * 文件路径(绝对) * @param response * 响应对象 */ public static void download(String path, HttpServletResponse response) { File file = new File(path); InputStream fis = null; OutputStream os = null; try { if (!file.exists()) { response.getWriter().print("文件不存在"); } // 以流的形式下载文件 fis = new BufferedInputStream(new FileInputStream(file)); // 设置响应报头 response.reset(); response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(file.getName(), ENCODING)); response.addHeader("Content-Length", "" + file.length()); response.setContentType(MIME_TYPE_BIN); response.setCharacterEncoding(ENCODING); // 写入响应流数据 os = new BufferedOutputStream(response.getOutputStream()); byte[] bytes = new byte[1024]; while (fis.read(bytes) != -1) { os.write(bytes); } } catch (Throwable e) { if (e instanceof ClientAbortException) { // 浏览器点击取消 LOGGER.info("用户取消下载!"); } else { e.printStackTrace(); } } finally { try { if (os != null) { os.close(); } if (fis != null) { fis.close(); } } catch (IOException e) { e.printStackTrace(); } } } /** * 下载服务器已存在的文件,支持断点续传 * * @param request * 请求对象 * @param response * 响应对象 * @param path * 文件路径(绝对) */ public static void download(HttpServletRequest request, HttpServletResponse response, File proposeFile) { LOGGER.debug("下载文件路径:" + proposeFile.getPath()); InputStream inputStream = null; OutputStream bufferOut = null; try { // 设置响应报头 long fSize = proposeFile.length(); response.setContentType("application/x-download"); // Content-Disposition: attachment; filename=WebGoat-OWASP_Developer-5.2.zip response.addHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(proposeFile.getName(), ENCODING)); // Accept-Ranges: bytes response.setHeader("Accept-Ranges", "bytes"); long pos = 0, last = fSize - 1, sum = 0;// pos开始读取位置; last最后读取位置; sum记录总共已经读取了多少字节 if (null != request.getHeader("Range")) { // 断点续传 response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT); try { // 情景一:RANGE: bytes=2000070- 情景二:RANGE: bytes=2000070-2000970 String numRang = request.getHeader("Range").replaceAll("bytes=", ""); String[] strRange = numRang.split("-"); if (strRange.length == 2) { pos = Long.parseLong(strRange[0].trim()); last = Long.parseLong(strRange[1].trim()); } else { pos = Long.parseLong(numRang.replaceAll("-", "").trim()); } } catch (NumberFormatException e) { LOGGER.error(request.getHeader("Range") + " is not Number!"); pos = 0; } } long rangLength = last - pos + 1;// 总共需要读取的字节 // Content-Range: bytes 10-1033/304974592 String contentRange = new StringBuffer("bytes ").append(pos).append("-").append(last).append("/").append(fSize).toString(); response.setHeader("Content-Range", contentRange); // Content-Length: 1024 response.addHeader("Content-Length", String.valueOf(rangLength)); // 跳过已经下载的部分,进行后续下载 bufferOut = new BufferedOutputStream(response.getOutputStream()); inputStream = new BufferedInputStream(new FileInputStream(proposeFile)); inputStream.skip(pos); byte[] buffer = new byte[1024]; int length = 0; while (sum < rangLength) { length = inputStream.read(buffer, 0, ((rangLength - sum) <= buffer.length ? ((int) (rangLength - sum)) : buffer.length)); sum = sum + length; bufferOut.write(buffer, 0, length); } } catch (Throwable e) { if (e instanceof ClientAbortException) { // 浏览器点击取消 LOGGER.info("用户取消下载!"); } else { LOGGER.info("下载文件失败...."); e.printStackTrace(); } } finally { try { if (bufferOut != null) { bufferOut.close(); } if (inputStream != null) { inputStream.close(); } } catch (IOException e) { e.printStackTrace(); } } } public static void downloadWithoutEncode(HttpServletRequest request, HttpServletResponse response, File proposeFile) { LOGGER.debug("下载文件路径:" + proposeFile.getPath()); InputStream inputStream = null; OutputStream bufferOut = null; try { // 设置响应报头 long fSize = proposeFile.length(); response.setContentType("application/x-download"); response.addHeader("Content-Disposition", "attachment; filename=" + proposeFile.getName()); response.setHeader("Accept-Ranges", "bytes"); long pos = 0, last = fSize - 1, sum = 0;// pos开始读取位置; last最后读取位置; sum记录总共已经读取了多少字节 if (null != request.getHeader("Range")) { // 断点续传 response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT); try { // 情景一:RANGE: bytes=2000070- 情景二:RANGE: bytes=2000070-2000970 String numRang = request.getHeader("Range").replaceAll("bytes=", ""); String[] strRange = numRang.split("-"); if (strRange.length == 2) { pos = Long.parseLong(strRange[0].trim()); last = Long.parseLong(strRange[1].trim()); } else { pos = Long.parseLong(numRang.replaceAll("-", "").trim()); } } catch (NumberFormatException e) { LOGGER.error(request.getHeader("Range") + " is not Number!"); pos = 0; } } long rangLength = last - pos + 1;// 总共需要读取的字节 // Content-Range: bytes 10-1033/304974592 String contentRange = new StringBuffer("bytes ").append(pos).append("-").append(last).append("/").append(fSize).toString(); response.setHeader("Content-Range", contentRange); // Content-Length: 1024 response.addHeader("Content-Length", String.valueOf(rangLength)); // 跳过已经下载的部分,进行后续下载 bufferOut = new BufferedOutputStream(response.getOutputStream()); inputStream = new BufferedInputStream(new FileInputStream(proposeFile)); inputStream.skip(pos); byte[] buffer = new byte[1024]; int length = 0; while (sum < rangLength) { length = inputStream.read(buffer, 0, ((rangLength - sum) <= buffer.length ? ((int) (rangLength - sum)) : buffer.length)); sum = sum + length; bufferOut.write(buffer, 0, length); } } catch (Throwable e) { if (e instanceof ClientAbortException) { // 浏览器点击取消 LOGGER.info("用户取消下载!"); } else { LOGGER.info("下载文件失败...."); e.printStackTrace(); } } finally { try { if (bufferOut != null) { bufferOut.close(); } if (inputStream != null) { inputStream.close(); } } catch (IOException e) { e.printStackTrace(); } } } /** * @param path * 文件路径(绝对) * @param response * 响应对象 * @return */ public static Boolean download(String path, HttpServletResponse response, String filename) { Boolean isBoolean = false; File file = new File(path); InputStream fis = null; OutputStream os = null; try { if (!file.exists()) { response.getWriter().print("文件不存在"); } // 以流的形式下载文件 fis = new BufferedInputStream(new FileInputStream(file)); // 设置响应报头 response.reset(); response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filename.trim(), ENCODING)); response.addHeader("Content-Length", "" + file.length()); response.setContentType(MIME_TYPE_BIN); response.setCharacterEncoding(ENCODING); // 写入响应流数据 os = new BufferedOutputStream(response.getOutputStream()); byte[] bytes = new byte[1024]; while (fis.read(bytes) != -1) { os.write(bytes); } isBoolean = true; } catch (Throwable e) { if (e instanceof ClientAbortException) { // 浏览器点击取消 isBoolean = false; LOGGER.info("用户取消下载!"); } else { isBoolean = false; e.printStackTrace(); } } finally { try { if (os != null) { os.close(); } if (fis != null) { fis.close(); } } catch (IOException e) { e.printStackTrace(); } } return isBoolean; }
时间: 2024-11-08 09:52:18