Guía de descarga de archivos web Java

Antecedentes

Hoy, ajusté la función de descarga de informes de un proyecto antiguo. El archivo original se almacenó localmente en el servidor. La descarga se puede obtener directamente desde la máquina local. Ahora tenemos que cambiarla para obtener el archivo del servidor FTP y devolverlo a la recepción.

En teoría, el código se puede ajustar ligeramente, pero en realidad es un pequeño pozo. Este artículo clasificará el proceso y los puntos de atención para descargar archivos de aplicaciones web Java.

Proceso de descarga de archivos

La descarga de archivos es una característica anticuada. El principio básico es escribir datos directamente en la secuencia de respuesta y establecer el tipo de respuesta en formato de secuencia binaria:

  1. Establecer el código de respuesta;
  2. Establezca el tipo de archivo de respuesta octet-stream;
  3. Establezca el nombre del archivo adjunto del campo de encabezado de respuesta;
  4. Quiero escribir datos en la secuencia OutputStream de ServletResponse.

Los códigos correspondientes para el segundo, tercer y cuarto pasos son:

Inserte la descripción de la imagen aquí

Descargar el código fuente de la operación

Los códigos de descarga de archivos comunes son:

	@ResponseBody
	@RequestMapping(value = "/download")
	public void download(HttpServletRequest request, HttpServletResponse response,String reportId) {
		// TODO 根据 reportId 查询报表对应的文件名称
		String fileName = "xxx日报表文件.xlsx";

		//设置响应类型和附件头域
		response.setCharacterEncoding("utf-8");
		response.setContentType("application/octet-stream");
		response.setHeader("content-disposition", "attachment;filename="+ fileName);

		//读取报表内容写入响应流对象
		InputStream inputStream = null;
		try {
			OutputStream output = response.getOutputStream();

			//检查文件是否存在
			if(!isFileExist(fileName)){
				logger.warn("文件/目录 {} 不存在", pathName);
				response.getWriter().println("报表文件不存在!");
				return;
			}

			inputStream = new FileInputStream(new File(pathName));
			int len = -1;
			byte[] bytes = new byte[2048];
           // 向 Response 的响应流写入二进制数据
			while ((len = inputStream.read(bytes)) != -1) {
				output .write(bytes, 0, len);
			}
			output.flush();
		} catch (Exception e) {
			logger.error("下载文件异常",e);
			try {
				response.getWriter().println("下载文件异常!");
			} catch (IOException ex) {
				ex.printStackTrace();
			}
		}finally{
			if(output != null){
				try {
					output.close();
				} catch (IOException e) {
					logger.error("下载文件关闭输出流异常",e);
				}
			}
			if(inputStream != null){
				try {
					inputStream.close();
				} catch (IOException e) {
					logger.error("下载文件关闭输入流异常",e);
				}
			}
		}
	}
复制代码

敲重点Después de ejecutar la operación de descarga, el archivo de informe de tipo xlsx se encuentra ahora en la barra de descarga. El encabezado de respuesta para ver la solicitud de red es:

Inserte la descripción de la imagen aquí

Ubicación del ajuste del campo del encabezado de respuesta

campo de encabezado de respuesta ajustado y la información de tipo debe ser en writeantes de escribir , de lo contrario, es el apego ilegible. Ajuste la secuencia del código, escriba y configure el encabezado de respuesta:

Inserte la descripción de la imagen aquí
Después de realizar la operación de descarga, se descubrió que el informe xlsx se descargó en el formato de paquete comprimido .zip y que el contenido no se podía leer.

Al observar el encabezado de la respuesta de la red, se puede ver que el campo del encabezado establecido después no ha tenido efecto:

Inserte la descripción de la imagen aquí

Programando Apocalipsis

¿Por qué el orden de visualización de los archivos adjuntos de descarga es diferente cuando el orden de configuración es diferente?

Verify repitió una docena de veces, que se encuentran response.setHeaderen writeel tiempo después de la operación, sistema de cabecera no es válido. Se especula que esto está determinado por el orden de ensamblaje de los paquetes de protocolo de comunicación http 因为 http 响应头域信息是在 body 之前组装的.

Finalmente, resuma los puntos principales de la descarga del archivo:

  1. Descargar ruta debe fijarse en el fondo, no podrá recibir la ruta de descarga de la recepción directa, de lo contrario existe ../..ningún riesgo de descargar una ruta de archivo, y si el camino que se ha recibido con fileNamelos parámetros, debe comprobar fileNameque no contiene ../otra vía especial;
  2. Debe prestar atención al orden de la configuración del campo del encabezado de respuesta y la operación de escritura de flujo 写设头域后写; de lo contrario, el archivo adjunto no está disponible;
  3. La misma descarga FTP de la ServletResponsedel OutputStreamobjeto pasado FTPClientes retrieveFile(filename, outputStream)descargado directamente a la corriente de salida.

Supongo que te gusta

Origin juejin.im/post/5e9a3393e51d4546b84780c7
Recomendado
Clasificación