diff --git a/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/storage/LimitedInputStream.java b/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/storage/LimitedInputStream.java
new file mode 100644
index 0000000000000000000000000000000000000000..c4c8ddfcf21552cc5a6b05ce6b74d9ab92b229d3
--- /dev/null
+++ b/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/storage/LimitedInputStream.java
@@ -0,0 +1,39 @@
+package de.ozgcloud.nachrichten.postfach.osiv2.storage;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import lombok.RequiredArgsConstructor;
+
+@RequiredArgsConstructor
+public class LimitedInputStream extends InputStream {
+	private final InputStream parentStream;
+	private final int limit;
+	private int readOffset = 0;
+
+	@Override
+	public int read() throws IOException {
+		var buffer = new byte[1];
+		var result = read(buffer, 0, 1);
+		return result < 0 ? result : buffer[0];
+	}
+
+
+	@Override
+	public int read(byte[] buffer, int offset, int length) throws IOException {
+		var remainingLength = limit - readOffset;
+		if (remainingLength > 0) {
+			var readLength = parentStream.read(buffer, offset, Math.min(remainingLength, length));
+			if (readLength > 0) {
+				readOffset += readLength;
+				return readLength;
+			}
+		}
+		return -1;
+	}
+
+	@Override
+	public void close() {
+		// Keep parent stream open
+	}
+}
diff --git a/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/storage/LimitedInputStreamTest.java b/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/storage/LimitedInputStreamTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..15c160042176f8ccac26c35f2cc6b2041460f462
--- /dev/null
+++ b/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/storage/LimitedInputStreamTest.java
@@ -0,0 +1,54 @@
+package de.ozgcloud.nachrichten.postfach.osiv2.storage;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+import java.io.ByteArrayInputStream;
+
+import org.apache.commons.io.IOUtils;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+import lombok.SneakyThrows;
+
+class LimitedInputStreamTest {
+
+	@DisplayName("should limit input stream")
+	@Test
+	@SneakyThrows
+	void shouldLimitInputStream() {
+		var inputStream = createExampleLimitedInputStream();
+
+		var result = IOUtils.toByteArray(inputStream);
+
+		assertEquals("12345", new String(result));
+	}
+
+	@DisplayName("should read one")
+	@Test
+	@SneakyThrows
+	void shouldReadOne() {
+		var inputStream = createExampleLimitedInputStream();
+
+		var result = inputStream.read();
+
+		assertEquals('1', result);
+	}
+
+	@DisplayName("should keep parent stream usable")
+	@Test
+	@SneakyThrows
+	void shouldKeepParentStreamUsable() {
+		var parentStream = new ByteArrayInputStream("123456789".getBytes());
+		var inputStream = new LimitedInputStream(parentStream, 5);
+		var inputStream2 = new LimitedInputStream(parentStream, 5);
+		IOUtils.toByteArray(inputStream);
+
+		var result = IOUtils.toByteArray(inputStream2);
+
+		assertEquals("6789", new String(result));
+	}
+
+	private LimitedInputStream createExampleLimitedInputStream() {
+		return new LimitedInputStream(new ByteArrayInputStream("123456789".getBytes()), 5);
+	}
+}
\ No newline at end of file