记录通过request.getInputStream()获取文件并保存到本地失败的问题

本文介绍了解决通过HTTP请求上传视频到服务器过程中出现的文件损坏问题。提供了两种有效的方法:使用Servlet API的Part对象和Spring MVC的MultipartFile进行文件读取与保存。

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

背景:

  通过前台上传一个视频,然后再保存到本地。

问题:

  通过request.getInputStream()获取输入流,FileOutputStream输出到本地。代码运行无异常,但是文件打开时错误。提示如图:

  

解决:

  方式一:

  使用request.getPart(String fileName);(适用于单文件)。多文件可用request.getParts();

	Part part = request.getPart("file");
	InputStream is = part.getInputStream();
	File file = new File("C:\\Users\\yyb\\Desktop\\part.mp4");
	FileOutputStream os = new FileOutputStream(file);
	byte[] bb = new byte[1024];
	int ch;
	while ((ch = is.read(bb)) > -1) {
		os.write(bb, 0, ch);
	}
	os.close();
	is.close();

  方式二:

  使用MultipartFile

	public String uploadFile(@RequestParam("test") MultipartFile file) {
		// 1判断文件是否为空
		if (file.isEmpty()) {
			return "文件为空";
		}
		// 2获取文件名
		String fileName = file.getOriginalFilename();
		// 3获取后缀
		String suffixName = fileName.substring(fileName.lastIndexOf("."));
		// 4路径
		String filePath = "E://springboot_fileUpload//";
		File dest = new File(filePath + fileName);
		// 5判断目录是否存在
		if (!dest.getParentFile().exists()) {
			// 不存在,创建
			dest.getParentFile().mkdirs();
		}
		try {
			file.transferTo(dest);
			return "上传成功";
		} catch (IllegalStateException | IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return "上传失败";
	}

 使用这两种方式。保存到本地的文件可以正常打开。

 

 

<think>首先,用户的问题是:“我想使用Java通过POST方法调用接口获取文件流的方式 请问Java 发送 POST 请求 获取文件流”。这是一个关于Java编程的问题,用户想了解如何使用POST方法调用接口来获取文件流。 根据系统级指令: - 所有行内数学表达式必须使用$...$格式,但这个问题不涉及数学表达式,所以不需要。 - 独立公式必须使用$$...$$格式单独成段,同样,这里没有数学公式。 - LaTeX语法正确:不需要。 - 使用中文回答:必须用中文。 - 生成相关问题:在回答后生成相关问题。 - 回答中引用的段落末尾自然地添加引用标识:需要引用提供的引用内容。 用户提供的引用: - 引用[1]:展示了一个Java方法,使用HttpURLConnection发送POST请求保存文件。 - 引用[2]:提到了RestTemplate和Httpclient发送POST请求。 - 引用[3]:涉及文件上传的content type判断。 - 引用[4]:提到了文件流的处理。 这些引用是关于Java发送POST请求获取文件流的代码示例。用户的问题聚焦在获取文件流上。 我的回答需要: - 结构清晰,帮助用户逐步解决问题。 - 保证回答真实可靠。 - 在回答中自然地引用这些内容。 回答结构: 1. **介绍问题**:简要解释用户的需求。 2. **逐步指导**:提供使用Java发送POST请求获取文件流的方法。包括使用HttpURLConnection的示例,因为引用[1]和[4]直接相关。 3. **代码示例**:基于引用[1],给出一个修改后的代码示例,专注于获取文件流而不是直接保存文件。 4. **其他方法**:提到使用RestTemplate或HttpClient(如引用[2]所示),但保持简洁,因为用户指定了POST和文件流。 5. **注意事项**:包括错误处理、编码、超时设置等。 6. **引用标识**:在引用相关段落时添加[^n]。 7. **生成相关问题**:在最后添加相关问题。 关键点: - 用户想获取文件流,而不是直接保存文件。引用[1]的代码保存文件到磁盘,但用户可能需要流处理。 - 所以,我会调整代码,展示如何获取InputStream,用户可以进一步处理它。 修改引用[1]的代码以获取文件流: - 在代码中,当响应码为HTTP_OK时,获取InputStream。 - 然后,用户可以选择保存文件或处理流。 生成相关问题: - 基于主题,如优化、错误处理、其他库等。 最终回答大纲: 1. 介绍:解释使用Java发送POST请求获取文件流的方法。 2. 方法一:使用HttpURLConnection(基于引用[1])。 - 代码示例。 3. 方法二:简要提及其他方法(如RestTemplate或HttpClient)。 4. 注意事项。 5. 相关问题。</think>### Java 发送 POST 请求获取文件流的方法 在 Java 中,通过 POST 方法调用接口获取文件流是常见的需求,例如下载文件或处理 API 返回的二进制数据。以下是基于标准 Java 库(如 `java.net.HttpURLConnection`)的逐步实现方法。整个过程包括设置请求、发送参数、处理响应流,确保资源正确关闭。参考您提供的引用内容,我将重点展示如何直接获取文件流(`InputStream`),而不是直接保存文件,以便您灵活处理流数据(如实时解析或转存)。 #### 步骤说明 1. **创建连接设置请求参数**:使用 `HttpURLConnection` 建立 POST 请求,指定 URL、超时和编码。 2. **写入请求体**:如果接口需要参数(如 JSON 或表单数据),通过输出流写入。 3. **处理响应**:检查 HTTP 状态码,成功时获取输入流(`InputStream`)。 4. **资源管理**:使用 try-with-resources 确保流和连接自动关闭,避免内存泄漏。 5. **错误处理**:捕获异常记录日志。 #### 代码示例(使用 HttpURLConnection) 以下方法演示了如何发送 POST 请求返回文件流。代码基于引用[1]和引用[4]优化,专注于获取 `InputStream`,您可以根据需要保存文件或直接处理流。 ```java import java.io.*; import java.net.HttpURLConnection; import java.net.URL; import java.nio.charset.StandardCharsets; public class FileStreamFetcher { /** * 发送 POST 请求获取文件流 * @param url 接口 URL * @param params 请求参数(如 JSON 字符串) * @return 文件流的 InputStream,如果失败返回 null */ public InputStream fetchFileStream(String url, String params) { HttpURLConnection conn = null; try { // 1. 创建配置连接 conn = (HttpURLConnection) new URL(url).openConnection(); conn.setRequestMethod("POST"); conn.setConnectTimeout(45000); // 45秒超时 conn.setReadTimeout(45000); conn.setRequestProperty("Charset", "UTF-8"); conn.setRequestProperty("Content-Type", "application/json;charset=UTF-8"); // 假设发送 JSON conn.setDoOutput(true); // 允许写入参数 conn.setDoInput(true); // 允许读取响应 // 2. 写入请求参数 try (OutputStream outputStream = conn.getOutputStream()) { byte[] input = params.getBytes(StandardCharsets.UTF_8); outputStream.write(input, 0, input.length); } // 3. 检查响应状态码 int responseCode = conn.getResponseCode(); if (responseCode == HttpURLConnection.HTTP_OK) { // 4. 获取文件流(InputStream) return conn.getInputStream(); // 返回流供外部处理 } else { System.err.println("请求失败,状态码: " + responseCode); return null; } } catch (Exception e) { e.printStackTrace(); return null; } finally { // 注意:InputStream 需要在外部关闭,连接在流关闭后自动释放 if (conn != null) { conn.disconnect(); // 断开连接 } } } // 示例用法:保存流到文件或直接处理 public static void main(String[] args) { FileStreamFetcher fetcher = new FileStreamFetcher(); String apiUrl = "https://example.com/api/download"; String jsonParams = "{\"fileId\": \"123\"}"; // 示例参数 try (InputStream inputStream = fetcher.fetchFileStream(apiUrl, jsonParams)) { if (inputStream != null) { // 处理文件流:例如保存本地文件 String savePath = "C:/downloads/file.zip"; try (FileOutputStream out = new FileOutputStream(savePath)) { byte[] buffer = new byte[1024]; int bytesRead; while ((bytesRead = inputStream.read(buffer)) != -1) { out.write(buffer, 0, bytesRead); } } System.out.println("文件保存成功至: " + savePath); } else { System.out.println("获取文件失败"); } } catch (IOException e) { e.printStackTrace(); } } } ``` #### 关键注意事项 1. **请求头设置**:根据接口要求调整 `Content-Type`,如 `application/x-www-form-urlencoded` 或 `multipart/form-data`(上传文件时参考引用[3])。如果接口不需要参数,可省略写入步骤。 2. **流处理**:返回的 `InputStream` 必须在外部使用后关闭(如通过 try-with-resources),否则会导致资源泄漏。在 `main` 方法中,我演示了如何保存流到文件。 3. **性能优化**: - 使用缓冲区(如 `byte[1024]`)提高读写效率。 - 设置合理的超时(`setConnectTimeout` 和 `setReadTimeout`),避免线程阻塞。 4. **错误处理**:添加更详细的日志或重试逻辑,以应对网络不稳定(引用[1]中使用了简单异常打印)。 5. **替代方法**: - **使用 RestTemplate(Spring 项目)**:简化代码,但需依赖 Spring 框架。引用[2]提到的方法示例: ```java RestTemplate restTemplate = new RestTemplate(); HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); HttpEntity<String> request = new HttpEntity<>(params, headers); ResponseEntity<byte[]> response = restTemplate.postForEntity(url, request, byte[].class); InputStream inputStream = new ByteArrayInputStream(response.getBody()); // 获取流 ``` - **使用 Apache HttpClient**:更灵活,适合复杂场景(如多部分上传,参考引用[3])。 #### 引用说明 - 在连接配置和流处理中,参考了 `HttpURLConnection` 的基础用法[^1]。 - 请求头设置借鉴了内容类型判断的通用实践[^3]。 - 文件流读写优化了缓冲区管理[^4]。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值