Java后端如何在处理Multipart POST请求前确定文件大小?
在JAX-RS中处理文件上传前获取文件大小的实用方案
看到你现在用JAX-RS处理文件上传,想要在处理POST请求前先确定文件大小,避免不必要的资源消耗对吧?我给你几个靠谱的方案,结合你的代码来调整:
方案1:用FormDataBodyPart替代直接注入InputStream
这是最直接的修改方式,FormDataBodyPart能帮你在读取文件流之前就拿到文件大小,而且比FormDataContentDisposition的getSize()更可靠(后者依赖客户端传的头,可能不准或缺失)。
修改后的代码示例:
// 定义允许的最大文件大小,比如10MB private static final long MAX_ALLOWED_SIZE = 10 * 1024 * 1024; @POST @Consumes(MediaType.MULTIPART_FORM_DATA) public Response uploadFile( @FormDataParam("file") FormDataBodyPart filePart ) throws IOException { // 第一步:先获取文件大小并检查 long fileSize = filePart.getSize(); if (fileSize > MAX_ALLOWED_SIZE) { return Response.status(Response.Status.PAYLOAD_TOO_LARGE) .entity("文件大小超过限制!最大允许:" + MAX_ALLOWED_SIZE / (1024*1024) + "MB") .build(); } // 第二步:再获取你需要的文件信息和输入流 FormDataContentDisposition fileDetail = filePart.getFormDataContentDisposition(); InputStream uploadedInputStream = filePart.getEntityAs(InputStream.class); String uploadedFileLocation = "somePath" + fileDetail.getFileName(); writeToFile(uploadedInputStream, uploadedFileLocation); String output = "File uploaded to : " + uploadedFileLocation; return Response.status(Response.Status.OK).entity(output).build(); }
为什么这个方法好用?
FormDataBodyPart会自动解析multipart表单的每个部分,getSize()返回的是该文件part的实际大小(只要客户端不是用chunked编码上传)。- 可以在读取流之前就拦截大文件,避免后续的IO操作浪费资源。
方案2:用请求过滤器(ContainerRequestFilter)提前拦截
如果想在请求到达你的资源方法之前就完成大小检查(比如全局统一限制所有文件上传),可以用JAX-RS的过滤器机制:
@Provider @PreMatching public class FileUploadSizeFilter implements ContainerRequestFilter { // 全局最大文件大小,比如15MB private static final long MAX_FILE_SIZE = 15 * 1024 * 1024; @Override public void filter(ContainerRequestContext requestContext) throws IOException { // 只处理multipart/form-data类型的请求 if (MediaType.MULTIPART_FORM_DATA_TYPE.isCompatible(requestContext.getMediaType())) { // 缓存请求体,避免流被一次性消耗后无法再用 CachedBodyEntity cachedEntity = new CachedBodyEntity(requestContext.getEntityStream()); requestContext.setEntityStream(cachedEntity.getInputStream()); // 解析multipart表单 MultipartFormDataMultiPart multiPart = cachedEntity.getEntity(MultipartFormDataMultiPart.class); FormDataBodyPart filePart = multiPart.getField("file"); if (filePart != null) { long fileSize = filePart.getSize(); if (fileSize > MAX_FILE_SIZE) { // 直接返回错误,中断请求 requestContext.abortWith(Response.status(Response.Status.PAYLOAD_TOO_LARGE) .entity("文件过大!最大支持" + MAX_FILE_SIZE/(1024*1024) + "MB") .build()); } } } } }
注意事项
- 如果客户端用chunked编码上传(没有Content-Length头),
getSize()会返回-1,这时候你没办法提前获取大小,只能在写入文件时计算,或者依赖服务器的全局配置(比如Tomcat的maxPostSize、Jetty的maxFormContentSize)来限制请求总大小。 FormDataContentDisposition.getSize()不要依赖,这个值是客户端通过Content-Disposition头传递的,可能被篡改或者省略,准确性不如FormDataBodyPart.getSize()。
这样调整后,你就能在处理文件上传前有效检查文件大小啦!
内容的提问来源于stack exchange,提问作者A.Dumas
相关产品推荐
相关产品推荐

