Quarkus是否原生支持MongoDB GridFS?大文件存储场景咨询
Quarkus + MongoDB GridFS 大文件上传/下载实现方案
核心问题解答
Quarkus的quarkus-mongodb-client扩展原生支持GridFS,它基于官方MongoDB Java驱动,而驱动本身提供了完整的GridFS操作API。Quarkus官方文档未单独针对GridFS做专项说明,但可以直接通过驱动API实现大文件的存储与检索需求,无需依赖Apache Camel。
方案一:纯Quarkus实现(基于MongoDB Client)
1. 添加依赖
在pom.xml中引入MongoDB Client扩展:
<dependency> <groupId>io.quarkus</groupId> <artifactId>quarkus-mongodb-client</artifactId> </dependency>
2. 配置MongoDB连接
在application.properties中配置MongoDB地址与目标数据库:
quarkus.mongodb.connection-string=mongodb://localhost:27017 quarkus.mongodb.database=file-storage
3. 大文件上传接口(Multipart Form)
创建REST接口接收文件与自定义元数据,通过GridFSBucket将文件与元数据绑定存储:
import com.mongodb.client.gridfs.GridFSBucket; import com.mongodb.client.gridfs.GridFSUploadOptions; import jakarta.inject.Inject; import jakarta.ws.rs.Consumes; import jakarta.ws.rs.POST; import jakarta.ws.rs.Path; import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.Response; import org.jboss.resteasy.reactive.PartType; import org.jboss.resteasy.reactive.RestForm; import org.jboss.resteasy.reactive.multipart.FileUpload; import org.bson.Document; import org.bson.types.ObjectId; @Path("/files") public class FileResource { @Inject GridFSBucket gridFSBucket; // Quarkus自动注入GridFSBucket实例 @POST @Path("/upload") @Consumes(MediaType.MULTIPART_FORM_DATA) public Response uploadFile( @RestForm("file") FileUpload file, @RestForm("metadata") @PartType(MediaType.APPLICATION_JSON) Document metadata) { // 配置上传参数:附加元数据、自定义分块大小(默认256KB) GridFSUploadOptions options = new GridFSUploadOptions() .metadata(metadata) .chunkSizeBytes(256 * 1024); // 上传文件至GridFS,返回文件唯一ID ObjectId fileId = gridFSBucket.uploadFromStream(file.fileName(), file.uploadedFile().toFileInputStream(), options); return Response.ok(fileId.toHexString()).build(); } }
4. 大文件下载接口
通过文件ID检索并返回文件,同时可附带元数据信息:
import com.mongodb.client.gridfs.model.GridFSFile; import jakarta.ws.rs.GET; import jakarta.ws.rs.PathParam; import jakarta.ws.rs.core.Response; import org.bson.types.ObjectId; import org.bson.Document; import java.io.InputStream; @GET @Path("/download/{fileId}") public Response downloadFile(@PathParam("fileId") String fileId) { GridFSFile gridFSFile = gridFSBucket.find(new Document("_id", new ObjectId(fileId))).first(); if (gridFSFile == null) { return Response.status(Response.Status.NOT_FOUND).build(); } // 获取文件输入流 InputStream inputStream = gridFSBucket.openDownloadStream(gridFSFile.getObjectId()); // 返回文件,附带下载文件名与元数据 return Response.ok(inputStream) .header("Content-Disposition", "attachment; filename=\"" + gridFSFile.getFilename() + "\"") .header("X-File-Metadata", gridFSFile.getMetadata().toJson()) .build(); }
方案二:Apache Camel Quarkus集成实现
如果倾向于使用Camel的路由能力,可通过quarkus-camel-mongodb-gridfs扩展快速完成集成:
1. 添加依赖
<dependency> <groupId>org.apache.camel.quarkus</groupId> <artifactId>quarkus-camel-mongodb-gridfs</artifactId> </dependency>
2. 配置MongoDB连接
同方案一的application.properties配置,额外添加Camel GridFS组件配置:
camel.component.mongodb-gridfs.connection-string=mongodb://localhost:27017 camel.component.mongodb-gridfs.database=file-storage
3. Camel路由实现上传与下载
import org.apache.camel.builder.RouteBuilder; import jakarta.enterprise.context.ApplicationScoped; @ApplicationScoped public class FileRoute extends RouteBuilder { @Override public void configure() throws Exception { // 上传路由:接收Multipart请求,存储到GridFS并返回文件ID from("rest:post:/camel/files/upload?consumes=multipart/form-data") .setHeader("CamelMongoDbGridFSUploadMetadata", simple("${body.metadata}")) .setHeader("CamelMongoDbGridFSFilename", simple("${body.file.fileName}")) .to("mongodb-gridfs:myGridFS?operation=upload") .transform().simple("${header.CamelMongoDbGridFSFileId}"); // 下载路由:通过文件ID获取文件并返回 from("rest:get:/camel/files/download/{fileId}") .setHeader("CamelMongoDbGridFSFileId", simple("${header.fileId}")) .to("mongodb-gridfs:myGridFS?operation=downloadById") .setHeader("Content-Disposition", simple("attachment; filename=\"${header.CamelMongoDbGridFSFilename}\"")); } }
事务一致性说明
MongoDB GridFS将文件拆分为fs.chunks(分块数据)与fs.files(元数据)两个集合存储,驱动的GridFS API会保证文件元数据与分块的一致性:上传操作先写入分块,最后原子性写入元数据文档;下载时仅返回完整关联的文件,完全避免了文件系统与数据库分离带来的事务回滚问题,符合你将所有数据统一存储的需求。
内容的提问来源于stack exchange,提问作者Tim
相关产品推荐
相关产品推荐

