HttpServletResponse response(中文乱码、文件下载、定时刷新、控制缓存、重定向、注意事项)

本文深入探讨了在Servlet环境下如何通过HTTP响应头实现中文字符正确显示、文件下载、页面定时刷新、缓存控制及请求重定向等功能。详细介绍了相关代码实现,并通过实例演示了如何设置响应头以解决各种常见问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

可以在html中用<meta http-equiv="" content="">来模拟响应头信息,比如

<meta http-equiv="refresh" content="3;url='/Home/Index'" /> 三秒后,跳转到Home/Index页面


1、向浏览器输出中文乱码


A、乱码原因: 加密方式 和 解密方式 不同造成。

B、浏览器默认解密,一般是gb2313,如果加密方式也是gb2313则不会乱码,但是存在兼容性问题,一般建议手动指定。

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		// 方式一

		// 输出UTF-8的数据,有出现乱码问题,通知浏览器以UTF-8码表打开回送的数据
		// response.setHeader("content-type", "text/html;charset=UTF-8");
		response.setContentType("text/html;charset=UTF-8");
		String data = "你好";
		OutputStream out = response.getOutputStream();
		out.write(data.getBytes("UTF-8"));

		
		
		// 方式二

		// 更改response的码表,通知服务器用UTF-8码表去取response中的数据,然后写给客户机
		response.setCharacterEncoding("UTF-8");
		// 通知浏览器以UTF-8码表打开回送的数据
		// 调用了这句话,内部会执行response.setCharacterEncoding("UTF-8"); 因此可以省略此句。
		// response.setHeader("content-type", "text/html;charset=UTF-8");
		response.setContentType("text/html;charset=UTF-8");
		PrintWriter writer = response.getWriter();
		writer.write(data);
	}




2、response实现文件下载


	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		// 1.获取需要下载的文件
		String path = this.getServletContext().getRealPath(
				"/download/一直很安静.mp3");
		String filename = path.substring(path.lastIndexOf("\\") + 1);
		// System.out.println(filename);
		// 2.通知浏览器以下载方式打开
		// 如果文件名中包含中文,则文件名要进行URL编码,URLEncoding.encode;如果不进行编码则文件名显示错误并且不可下载。
		response.setHeader("content-disposition", "attachment;filename="
				+ URLEncoder.encode(filename, "UTF-8"));
		// 3.向浏览器写出数据
		FileInputStream in = null;
		try {
			OutputStream out = response.getOutputStream();
			in = new FileInputStream(path);
			byte buffer[] = new byte[1024];
			int len = 0;
			while ((len = in.read(buffer)) > 0) {
				out.write(buffer, 0, len);
			}
		} finally {
			if (in != null) {
				in.close(); // 关闭流
			}
		}
	}



3、refresh控制定时刷新


A、利用Response设置响应头refresh可以实现页面的定时刷新功能。

B、response.setHeader("Refresh",  "3");//3秒刷新一次当前页

C、response.setHeader("Refresh",  "3;url='/news/index.jsp'");//三秒后跳转到另外一个页面。

D、也可设置<meta http-equiv="refresh" content="3;url='/Home/Index'" /> 实现相同效果



4、 控制缓存


A、利用response设置expires响应头为0或-1浏览器就不会缓存当前资源。(同样功能的头还有Cache-Control:no-cache、Pragma: no-cache)

B、设置缓存文件

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {	
		
		// System.currentTimeMillis() 当前时间毫秒 ; 1000l 加l代表是long类型,相乘的结果也是long类型。
		response.setDateHeader("Expires", System.currentTimeMillis() + 1000l
				* 3600 * 24 * 30);

		InputStream in = new FileInputStream(this.getServletContext()
				.getRealPath("1.jpg"));
		OutputStream out = response.getOutputStream();

		byte[] bs = new byte[1024];
		int i = 0;
		while ((i = in.read(bs)) != -1) {
			out.write(bs, 0, i);
		}
		in.close();
	}


5、response实现请求重定向


A、response.sendRedirec("....");//是 发送两次请求

B、利用 HttpContext 转发实现重定向 是一次请求

		/* 要利用ServletContext对象实现转发 */
		this.getServletContext().getRequestDispatcher("/index.jsp").forward(request, response);



6、getOutputStream和getWriter方法冲突的问题


A、getOutputStreamgetWriter这两个方法互相排斥,调用了其中的任何一个方法后,就不能再调用另一方法。  

B、lSerlvetservice方法结束后,Servlet引擎将检查getWritergetOutputStream方法返回的输出流对象是否已经调用过close方法,如果没有,Servlet引擎tomcat将调用close方法关闭该输出流对象。



<think>我们要解决Java中使用response.getOutputStream()生成的文件无法打开的问题。根据引用内容,可能的异常包括"getOutputStream()hasalreadybeencalledforthisresponse"和"IllegalStateException"等。同时,我们还看到一些解决方案和建议。下面将逐步分析问题并提供解决方案。###问题分析1.**异常原因**:在Servlet或JSP中,当多次调用`getOutputStream()`或`getWriter()`时,会抛出`IllegalStateException`。因为Servlet规范规定,在一个响应中只能使用其中一种方法(字节流或字符流),不能同时使用。2.**文件无法打开**:除了上述异常,文件无法打开可能是由于以下原因:-文件内容未正确写入。-响应头设置不正确(如Content-Type、Content-Disposition等)。-文件传输过程中发生中断或编码问题。###解决方案根据引用[1]和[4],我们可以采用以下步骤:####1.确保只调用一次`getOutputStream()`在同一个响应中,确保只调用一次`getOutputStream()`,不要混合使用`getWriter()`和`getOutputStream()`。####2.正确设置响应头在下载文件前,必须设置以下响应头:```javaresponse.setContentType("application/octet-stream");//或者具体MIME类型,如application/vnd.ms-excelresponse.setHeader("Content-Disposition","attachment;filename="+fileName);```####3.使用`reset()`和`clear()`方法(仅当出现异常时)如果在调用`getOutputStream()`前已经调用了其他输出方法,可以在适当位置使用`reset()`和`clear()`。如引用[1]提到:-在JSP中,可以尝试在末尾添加:```jsp<%out.clear();out=pageContext.pushBody();%>```-在Servlet中,可以尝试:```javaresponse.reset();//注意:如果响应已提交(committed),调用reset()会抛出IllegalStateExceptionServletOutputStreamout=response.getOutputStream();```####4.确保写入数据正确使用`OutputStream`写入文件时,确保数据正确生成并刷新输出流:```javaOutputStreamout=response.getOutputStream();//生成文件内容(例如使用Aspose.Words生成Word文档,或使用POI生成Excel)Documentdoc=newDocument();//...操作docdoc.save(out,SaveOptions.createSaveOptions(SaveFormat.DOCX));//最后刷新并关闭out.flush();out.close();```####5.避免其他输出确保在文件下载的Servlet或JSP中没有额外的输出,例如不要使用`System.out.println`输出到控制台(这可能会被重定向到响应流),或者避免在JSP中混入HTML文本。####6.使用完整示例代码以下是一个在Servlet中下载文件的完整示例:```javaprotectedvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse)throwsServletException,IOException{//设置响应头response.setContentType("application/vnd.ms-excel");response.setHeader("Content-Disposition","attachment;filename=\"example.xls\"");try{//获取输出流ServletOutputStreamout=response.getOutputStream();//创建Excel文件(示例,使用字符串模拟)StringexcelData="Name\tAge\nJohn\t25\nJane\t30";out.write(excelData.getBytes());out.flush();out.close();}catch(Exceptione){e.printStackTrace();response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,"生成文件失败");}}```###注意事项-如果使用JSP做下载,应避免在JSP开头或中间输出任何内容(包括空格和换行),否则可能导致文件头被破坏。建议使用Servlet处理下载。-如果使用JSP且出现`getOutputStream()`多次调用的问题,参考引用[1]的解决方案:在JSP末尾加上`out.clear();out=pageContext.pushBody();`。###问题拓展如果按照上述步骤操作后仍然无法打开文件,请检查:-生成文件内容的代码是否正确?例如,使用Aspose.Words生成Word时,是否生成了正确格式的字节?-文件扩展名和Content-Type是否匹配?-是否可以尝试将生成的文件先保存到服务器磁盘,检查是否正常?如果可以,则问题可能出在下载流传输上。§§相关问题§§1.JavaServlet下载文件时响应头如何正确设置?2.如何避免在Servlet响应中重复调用输出流?3.使用Aspose.Words生成Word并下载时有哪些注意事项?4.JavaWeb应用中如何实现文件下载功能?</think> ### Java中使用`response.getOutputStream()`生成文件无法打开的解决方案 根据引用内容[1][2][4]中提到的常见问题及解决方案,以下是可能导致文件无法打开的完整排查步骤: #### 1. **避免输出流重复调用(核心问题)** ```java // 在所有输出操作前重置响应 response.reset(); // 清除潜在的缓存 out.clear(); // 重新获取输出流(关键步骤) ServletOutputStream outStream = response.getOutputStream(); ``` > **注意**:若出现`IllegalStateException`(引用[1][2]),说明响应头已提交,此时只能执行: > ```java > out.clear(); > out = pageContext.pushBody(); // 适用于JSP > ``` #### 2. **必须设置的响应头(缺少会导致文件损坏)** ```java // 设置MIME类型(Excel示例) response.setContentType("application/vnd.ms-excel"); // 强制浏览器下载而非预览 response.setHeader("Content-Disposition", "attachment;filename=example.xlsx"); // 关闭缓存保证最新数据 response.setHeader("Pragma", "no-cache"); response.setHeader("Cache-Control", "no-cache"); ``` #### 3. **路径处理关键点(引用[4]特殊要求)** ```java // 绝对路径需添加"file:"前缀(引用[4]) String filePath = "file:D:/workspace/file.xls"; File file = new File(new URI(filePath)); ``` #### 4. **文件生成最佳实践** ```java try (OutputStream out = response.getOutputStream(); Workbook workbook = new HSSFWorkbook()) { // 示例:Apache POI生成Excel Sheet sheet = workbook.createSheet("Data"); Row row = sheet.createRow(0); row.createCell(0).setCellValue("正确生成"); workbook.write(out); // 直接写入输出流 out.flush(); } catch (Exception e) { response.sendError(500, "文件生成失败"); } ``` #### 5. **常见问题排查表** | 现象 | 解决方案 | |------|----------| | 下载0字节文件 | 检查`out.flush()`是否执行 | | 文件内容乱码 | 添加`response.setCharacterEncoding("UTF-8")` | | 浏览器直接打开乱码 | 确认`Content-Disposition`中的`attachment`参数 | | 报IllegalStateException | 避免在JSP中混用`<%= %>`和`getOutputStream()` | | Word/Excel提示损坏 | 用`Aspose.Words`等专业库(引用[3])替代手动生成 | > **特殊场景处理**:当使用Aspose等组件时: > ```java > Document doc = new Document(); > // ...构建文档内容... > doc.save(out, SaveFormat.DOCX); // 直接输出到响应流 > ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值