Ich entwickle Form Submission Service mit Jersey 2.0. Das Formular enthält mehrere Text Felder und eine Datei Feld. Ich brauche Datei, Dateinamen, Datei Medientyp und Datei Inhaltstyp und speichern Sie sie in Objektspeicher zu extrahieren.Upload von Jersey-Servicedateien verursacht OutOfMemoryError
@Path("upload")
@Consumes({MediaType.MULTIPART_FORM_DATA})
@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
public class UploadService {
@POST
public BlobDo uploadFile(FormDataMultiPart uploadedBody) {
String accountSid = uploadedBody.getField("account-sid").getValue();
String apiToken = uploadedBody.getField("api-token").getValue();
String checksum = uploadedBody.getField("checksum").getValue();
FormDataBodyPart bodyPart = uploadedBody.getField("file");
MySwiftObject obj = new MySwiftObject(bodyPart.getValueAs(InputStream.class));
obj.setName(bodyPart.getContentDisposition().getFileName());
obj.setContentType(bodyPart.getMediaType().toString());
obj.setContentDisposition(bodyPart.getContentDisposition().toString());
...
}
pom.xml
<jersey.version>2.17</jersey.version>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet-core</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.test-framework.providers</groupId>
<artifactId>jersey-test-framework-provider-inmemory</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-multipart</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-server</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.ext</groupId>
<artifactId>jersey-bean-validation</artifactId>
</dependency>
Formulareinreichung Anfrage
POST /nbs/v2/upload HTTP/1.1
Host: 127.0.0.1:8080
Cache-Control: no-cache
Postman-Token: a4c1d4e9-5f71-2321-3870-e9cac0524f8d
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryA2Z9pPMA7y3da8BG
------WebKitFormBoundaryA2Z9pPMA7y3da8BG
Content-Disposition: form-data; name="account-sid"
Q45Ppm5ukvdqjTQ6eW0O5ztTXipwnjKQx1p6cf+fbCQ=
------WebKitFormBoundaryA2Z9pPMA7y3da8BG
Content-Disposition: form-data; name="api-token"
6397cd691909fdc14cef67dbc1dc2dc3
------WebKitFormBoundaryA2Z9pPMA7y3da8BG
Content-Disposition: form-data; name="file"; filename="screen_4_100155.jpg"
Content-Type: image/jpeg
......Exif..MM.*.............................b...........j
------WebKitFormBoundaryA2Z9pPMA7y3da8BG
Content-Disposition: form-data; name="checksum"
6a3381b1d16bded4a3dfc325a8bb800e
------WebKitFormBoundaryA2Z9pPMA7y3da8BG
JVM-Heap-Größe
-Xmx=1024mb
Die
ProblemBeim Hochladen ~ 50MB Datei zwei temporäre Dateien mit ähnlichen MD5-Summen werden im Verzeichnis /tmp/tomcat7-tomcat7-tmp
mit Namen erstellt FileBackedOutputStream7949386530699987086.tmp
und MIME8234229766850016150.tmp
Bevor Upload abgeschlossen Server Ausnahme
javax.servlet.ServletException: org.glassfish.jersey.server.ContainerException: java.lang.OutOfMemoryError: Java heap space org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:421) org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:386) org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:335) org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:222)
werfen und löscht die Datei mit dem Namen MIME8234229766850016150.tmp
aber verlässt den anderen. Und gelöschte FileBackedOutputStream....tmp
Dateien füllen den gesamten Speicherplatz auf der Festplatte.
Was ich tat
erhöhen Heap-Speicher zu 7 GB, aber ~ 200 MB-Dateien können nicht hochgeladen werden.
Job auf dem Server ausführen, um alte temporäre Dateien zu löschen.
Erstellt Datei mit dem Namen
jersey-multipart-config.properties
und Inhaltjersey.config.multipart.bufferThreshold = -1
Die Datei MIME[random numbers].tmp
wird nicht mehr erstellt, aber FileBackedOutputStream[random number].tmp
hängt immer noch auf der Festplatte, es sei denn tomcat neu gestartet wird.
Frage
Wie kann Jersey große Dateien verarbeiten (vielleicht 1 GB) ohne temporäre Dateien auf meiner Festplatte zu verlassen? Der beste Fall wäre, keine Festplatte zu verwenden und kleine Stücke durch den Speicher zu übertragen.
Warum bekomme ich Heap-Überlauf, wenn Eingangsstrom mit Dateien gesichert wird?
Materialien Ich las
- Die Erklärung schließt die ich bisher gefunden. read
- Dieser Typ hat ein ähnliches Problem, aber auf der Client-Seite. read
- Kann Lösung enthalten, konnte aber die Antwort nicht verstehen. read
- Ziemlich nah an meinem Problem, aber kann es nicht ausarbeiten. read
- pufferThreshold Idee wurde von hier übernommen. read