背景:使用hutool工具进行文件上传。
直接上代码:
cn.hutool hutool-all 5.1.0
import cn.hutool.http.HttpRequest; import java.io.File; import java.util.*; //…… String urlString = "……/upload"; MapparamMap = new HashMap<>(); File file = new File("D:\soft\Anaconda3-2021.05-Windows-x86_64.exe"); paramMap.put("file", file); HttpRequest.post(urlString).form(paramMap).timeout(60*1000).execute().body();
当文件比较大的时候,就引发了OOM异常。
经过查阅HttpRequest源码发现它有一个字段:blockSize(Chuncked块大小,0或小于0表示不设置Chuncked模式),最终是设置到java.net.HttpURLConnection的chunkLength字段中。
Chuncked模式,即分块传输模式,
因此设置该值大于0即可解决该OOM问题。
附测试demo:
pom.xml:
4.0.0 cn.sky mytest 1.0-SNAPSHOT 8 8 org.springframework.boot spring-boot-starter-parent 2.1.3.RELEASE org.springframework.boot spring-boot-starter-web 2.2.2.RELEASE cn.hutool hutool-all 5.1.0 com.konghq unirest-java 3.11.12 com.alibaba fastjson 1.2.78 com.squareup.okhttp3 okhttp 3.13.1
MyController:
package cn.sky.mytest.controller;
import cn.hutool.http.HttpRequest;
import com.alibaba.fastjson.JSON;
import kong.unirest.HttpResponse;
import kong.unirest.Unirest;
import okhttp3.*;
import okhttp3.RequestBody;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
import java.util.*;
@RequestMapping("/myController")
@RestController
public class MyController {
@PostMapping("/upload")
public Object upload(@RequestParam(value = "file") MultipartFile file){
System.out.println(file.getOriginalFilename()+":"+(file.getSize()/1024/1024)+"M");
return "ok";
}
@GetMapping("/test")
public Object test(int type) throws IOException {
String urlString = "http://localhost:8080/myController/upload";
Map paramMap = new HashMap<>();
File file = new File("D:\soft\Anaconda3-2021.05-Windows-x86_64.exe");
paramMap.put("file", file);
if(type==1) {
int blockSize = 1024*10;
String body = HttpRequest.post(urlString)
.setChunkedStreamingMode(blockSize)
.form(paramMap).timeout(60*1000).execute().body();
System.out.println(body);
}else if(type==2){
String body = HttpRequest.post(urlString).form(paramMap).timeout(60*1000).execute().body();
System.out.println(body);
}else if(type==3){
HttpResponse stringHttpResponse = Unirest.post(urlString).fields(paramMap).asString();
System.out.println(stringHttpResponse.getStatus()+":"+stringHttpResponse.getBody());
}else if(type==4){
OkHttpClient client = new OkHttpClient().newBuilder()
.build();
MediaType mediaType = MediaType.parse("text/plain");
RequestBody body = new MultipartBody.Builder().setType(MultipartBody.FORM)
.addFormDataPart("file",file.getName(),RequestBody.create(MediaType.parse("application/octet-stream"),file))
.build();
Request request = new Request.Builder()
.url(urlString)
.method("POST", body)
.build();
Response response = client.newCall(request).execute();
System.out.println(JSON.toJSONString(response));
}
return "ok";
}
}
application.properties:
server.port=8080 #需要设置这个,否则文件太大会上传失败 spring.servlet.multipart.max-file-size = 1073741824 spring.servlet.multipart.max-request-size = 1073741824
启动脚本(限制内存为100M):
mvn spring-boot:run -Dspring-boot.run.jvmArguments="-Xmx100M -Xms100M"
访问地址:http://localhost:8080/myController/test?type=
type可为1,2,3,4,堆内存使用情况如下(文件为477M):
type=1:
type=2:
type=3:
type=4:



