as Hochladen der @Jersey-Servicedatei verursacht OutOfMemoryError
Ich entwickle einen Formularübermittlungsdienst mit Jersey 2.0. Das Formular enthält mehrereTex Felder und einDate Feld. Ich muss @ extrahierDate, Dateinam, Dateimedientyp und Datei Inhaltstyp und speichern Sie sie im Objektspeicher.
@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>
form Submission Request
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
Das ProbleBeim Hochladen einer ~ 50MB-Datei werden zwei temporäre Dateien mit ähnlichen MD5-Summen im Verzeichnis @ erstell/tmp/tomcat7-tomcat7-tmp
mit dem NamenFileBackedOutputStream7949386530699987086.tmp
undMIME8234229766850016150.tmp
Vor dem Hochladen ist der Server fertig, der eine Ausnahme auslöst
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)
und löscht die Datei mit dem NamenMIME8234229766850016150.tmp
verlässt aber den anderen. Und nicht gelöschteFileBackedOutputStream....tmp
Dateien füllen den gesamten Speicherplatz auf der Festplatte.
rhöhen Sie den Heap-Speicher auf 7 GB, aber es können keine ~ 200 MB-Dateien hochgeladen werde
Job auf dem Server ausführen, um alte temporäre Dateien zu löschen.
Erstellte Datei mit dem Namenjersey-multipart-config.properties
und content
jersey.config.multipart.bufferThreshold = -1
Die DateiMIME[random numbers].tmp
wird nicht mehr erstellt, aberFileBackedOutputStream[random number].tmp
hängt immer noch auf der Festplatte, es sei denn, Tomcat wird neu gestartet.
Wie kann Jersey mit großen Dateien (möglicherweise 1 GB) umgehen, ohne temporäre Dateien auf meiner Festplatte zu belassen? Der beste Fall wäre, überhaupt keine Festplatte zu verwenden und kleine Teile durch den Speicher zu übertragen.
Warum bekomme ichheap overflow Wenn der Eingabestream mit Dateien gesichert ist?
Materialien, die ich leseDie abschließende Erklärung habe ich bisher gefunden.leseDieser Typ hat ein ähnliches Problem, aber auf der Client-Seite.lese Kann Lösung enthalten, konnte aber die Antwort nicht verstehen.lesePretty nah an meinem Problem, kann es aber nicht klären.lese bufferThreshold Idee wurde von hier übernommen.lese