When files are uploaded via a form with Safari (v18.5) and the server (Tomcat v11.0.9) has HTTP/2 enabled, they're being corrupted.
The files I was able to replicate this with weren't small.. or overly large:
1.7M sample.HEIC
4.1M sample.jpg
2.1M sample.pdf
2.0M sample.txt
1.5M sample.zip
SHA256 Results:
Original Files
2ee389fa00d2190c5527eeb171c0eb7d8fe5a2f34c972954ba97c9675c4a0c84 sample.HEIC
8a2479fe45f93ff6901151817f257eccbdf0c673e3660124be90da5344f02958 sample.jpg
a5624f2b47bd8ee257bead36bb32a37ab4b01fa0675f608c1edf9c82c1a9f0f1 sample.pdf
e061f37ec0d2d64e74675287a9d93f22d7a4090193f60f1fdc5b9961f34b0f43 sample.txt
da0429d51bb6a11c3154c0d04a5fc3a6dcd902882e6ac9aa24532e1cebcc965c sample.zip
Uploaded Files via Chrome HTTP/1.1
2ee389fa00d2190c5527eeb171c0eb7d8fe5a2f34c972954ba97c9675c4a0c84 sample.HEIC
8a2479fe45f93ff6901151817f257eccbdf0c673e3660124be90da5344f02958 sample.jpg
a5624f2b47bd8ee257bead36bb32a37ab4b01fa0675f608c1edf9c82c1a9f0f1 sample.pdf
e061f37ec0d2d64e74675287a9d93f22d7a4090193f60f1fdc5b9961f34b0f43 sample.txt
da0429d51bb6a11c3154c0d04a5fc3a6dcd902882e6ac9aa24532e1cebcc965c sample.zip
Uploaded Files via Chrome HTTP/2
2ee389fa00d2190c5527eeb171c0eb7d8fe5a2f34c972954ba97c9675c4a0c84 sample.HEIC
8a2479fe45f93ff6901151817f257eccbdf0c673e3660124be90da5344f02958 sample.jpg
a5624f2b47bd8ee257bead36bb32a37ab4b01fa0675f608c1edf9c82c1a9f0f1 sample.pdf
e061f37ec0d2d64e74675287a9d93f22d7a4090193f60f1fdc5b9961f34b0f43 sample.txt
da0429d51bb6a11c3154c0d04a5fc3a6dcd902882e6ac9aa24532e1cebcc965c sample.zip
Uploaded Files via Safari HTTP/1.1
2ee389fa00d2190c5527eeb171c0eb7d8fe5a2f34c972954ba97c9675c4a0c84 sample.HEIC
8a2479fe45f93ff6901151817f257eccbdf0c673e3660124be90da5344f02958 sample.jpg
a5624f2b47bd8ee257bead36bb32a37ab4b01fa0675f608c1edf9c82c1a9f0f1 sample.pdf
e061f37ec0d2d64e74675287a9d93f22d7a4090193f60f1fdc5b9961f34b0f43 sample.txt
da0429d51bb6a11c3154c0d04a5fc3a6dcd902882e6ac9aa24532e1cebcc965c sample.zip
Uploaded Files via Safari HTTP/2
872ed65f6143e72eb19a2824937f99f4628bc0a369e6b020e9121976104ed0df sample.HEIC
34d5395731c764c32493b47f38f914700aaaaaf3b7fb0bce237073fdead8b9ec sample.jpg
cda31f8111cd5f4910d1af62a3db1a23720e8a434f2f39e71bc68e95b1d0e817 sample.pdf
6b63f7c6c77ad89c783558b7ef99228cb4cebd2308a76fbd71c66f439886f12c sample.txt
be9eddc53377cb229e4e78fdc4cd47084fb289e91733ce52e3c9e10a5ea59fdc sample.zip
Nothing uploaded correctly using Safari when Tomcat was using HTTP/2 (sometimes they did, but very rarely). There were also no errors in the Tomcat logs.
This occurs on the full application on the production environment with the following versions:
OS: Ubuntu 24.04.2 LTS
Java: Oracle 21.0.6
Tomcat: 11.0.9 (and version 10.1.28 before updating in an attempt to fix)
Replicated on a local dev environment with the following versions and example minimal code (using Spring Boot 3.5.2 with embedded Tomcat):
OS: macOS 15.5
Java: Oracle 21.0.6
Tomcat: 10.1.42
FileUploadApp.java
@SpringBootApplication
@Controller
public class FileUploadApp {
public static void main(String[] args) {
SpringApplication.run(FileUploadApp.class, args);
}
public static class UploadForm {
private MultipartFile file;
public MultipartFile getFile() {
return file;
}
public void setFile(MultipartFile file) {
this.file = file;
}
}
@GetMapping("/")
public String upload() {
return "upload";
}
@PostMapping("/")
public String upload(UploadForm uploadForm) throws IOException {
Path dest = Path.of("/tmp", uploadForm.getFile().getOriginalFilename());
uploadForm.getFile().transferTo(dest);
return "upload";
}
}
upload.html
<form action="/" enctype="multipart/form-data" method="POST">
<input type="file" name="file"/>
<input type="submit" title="Submit"/>
</form>
application.properties
spring.servlet.multipart.max-file-size=5MB
spring.servlet.multipart.max-request-size=5MB
server.ssl.enabled=true
server.ssl.key-store=classpath:keystore.p12
server.ssl.key-store-password=somepassword
server.ssl.key-store-type=PKCS12
server.ssl.key-alias=http2-alias
server.http2.enabled=true
Are there some other configuration settings in Tomcat, or something else that I missed elsewhere for Safari to work with HTTP/2?
In the Apache Software Foundation bug tracker I found this report from someone else having similar problems.
From the comments in that report, it looks like Safari is tripping the abusive behavior detection. Rather than disabling it, by setting overheadDataThreshold="2048"
everything now works as expected.
Tomcat documentation regarding these settings here.