我创建了一个扩展InputStream的类,这样我可以保持对正在读取的字节数的计数,如果超出我定义的最大限制,则抛出异常。
这是我的课程:
public class LimitedSizeInputStream extends InputStream
{
private final InputStream original;
private final long maxSize;
private long total;
public LimitedSizeInputStream(InputStream original, long maxSize)
{
this.original = original;
this.maxSize = maxSize;
}
@Override
public int read() throws IOException
{
int i = original.read();
if (i >= 0)
{
incrementCounter(1);
}
return i;
}
@Override
public int read(byte b[]) throws IOException
{
return read(b, 0, b.length);
}
@Override
public int read(byte b[], int off, int len) throws IOException
{
int i = original.read(b, off, len);
if (i >= 0)
{
incrementCounter(i);
}
return i;
}
private void incrementCounter(int size) throws IOException
{
total += size;
if (total > maxSize)
{
throw new IOException("InputStream exceeded maximum size in bytes.");
}
}
}
这来自:Copy InputStream, abort operation if size exceeds limit,我正在实现一个Jersey API,如果用户上传的文件太大,该API将会失败。
这是我的资源分类:
@POST
@Consumes(MediaType.MULTIPART_FORM_DATA)
@Path("/test")
public Response load(
@Context HttpServletRequest request,
@FormDataParam(FILE_FIELD) FormDataBodyPart file)
{
if (request.getContentLength() > MAX_FILE_SIZE_IN_BYTES)
{
// fail fast handle failure
}
try (InputStream metadataStream = new LimitedSizeInputStream(
file.getValueAs(InputStream.class), MAX_FILE_SIZE_IN_BYTES))
{
// some logic
}
catch (IOException e)
{
// handle failure
}
}
我在我的try资源中包装了LimitedSizeInputStream,所以我认为流应该正确关闭。我对是否正确处理关闭操作感到困惑,或者我是否正在通过LimitedSizeInputStream和file.getValueAs(InputStream.class)打开两个输入流,并且只有一个正在关闭?
try-with-resources仅关闭声明的资源。因此只会关闭metadataStream
。
您应该在close
中实现LimitedSizeInputStream
方法以关闭原始流。
@Override
public void close() throws IOException {
original.close();
}
如果LimitedSizeInputStream
扩展了InputStream
并包装了另一个流,那么@areus的解决方案是最好的解决方案。
一种替代方法是扩展FilterInputStream
,如下所示:
public class LimitedSizeInputStream extends FilterInputStream
{
private final long maxSize;
private long total;
public LimitedSizeInputStream(InputStream original, long maxSize)
{
super(original);
this.original = original;
this.maxSize = maxSize;
}
// use 'this.in' instead of 'this.original'
// at least one of the 'read' methods needs to be overridden.
}
请注意,FilterInputStream
提供了可能证明有用的API方法的默认实现。
javadoc提供了默认方法实现的详细信息。