用 java 实现对一个长度不确定的大文件 InputStream 的 http post 流式传输,但不要使用 chunked 模式,接收端边接收边处理,不要发生OOM
时间: 2024-03-18 07:44:38 浏览: 72
对于一个长度不确定的大文件,我们可以使用 Java 中的 HttpURLConnection 类来进行 http post 的流式传输。具体实现步骤如下:
1. 获取文件输入流,并创建 HttpURLConnection 连接对象,设置请求方法为 POST,设置请求头 Content-Type 为 multipart/form-data。
2. 设置请求头 Content-Length,这里我们需要先获取文件的大小,如果文件大小超过了一个较小的阈值(比如 10MB),则设置 Content-Length 为一个较大的值(比如 1GB),否则设置为文件大小。
3. 获取 HttpURLConnection 的输出流,将文件数据分段读取并写入输出流中。为了避免发生 OOM,我们可以定义一个缓冲区,每次读取一定长度的数据块到缓冲区中,再将缓冲区中的数据写入输出流。
4. 在读取文件数据的同时,我们可以监听 HttpURLConnection 的输入流,接收服务端返回的响应数据。如果服务端返回的状态码表明上传成功,则可以结束传输;否则可以根据需要进行重试或者中止传输。
下面是一个简单的示例代码,供参考:
```java
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
public class HttpPostStream {
private static final int BUFFER_SIZE = 1024 * 1024; // 1MB
public static void main(String[] args) throws IOException {
String url = "http://example.com/upload";
String filePath = "/path/to/large/file";
File file = new File(filePath);
long fileSize = file.length();
HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "multipart/form-data");
if (fileSize > 10 * 1024 * 1024) {
connection.setRequestProperty("Content-Length", "1G");
} else {
connection.setRequestProperty("Content-Length", String.valueOf(fileSize));
}
connection.setDoOutput(true);
OutputStream outputStream = connection.getOutputStream();
InputStream inputStream = new FileInputStream(file);
byte[] buffer = new byte[BUFFER_SIZE];
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
outputStream.flush();
if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
// handle error or retry
}
// process response data if needed
}
inputStream.close();
outputStream.close();
connection.disconnect();
}
}
```
在实际应用中,需要根据具体的需求进行一些细节的调整,比如设置连接超时时间、重试次数、调整缓冲区大小等。
阅读全文