如何通过GRPC流式传输大Zip文件?解决传输过大报错问题
GRPC大Zip文件流式传输解决方案
问题分析
你当前的代码一次性将整个大Zip文件读取到单个ByteString中,再封装成一个SourceResponse返回,这会导致内存占用过高,触发数据量过大的异常。要实现真正的流式传输,需要将文件分块读取并逐个发送响应。
解决方案
修改服务端代码,分块读取文件内容,流式生成多个SourceResponse:
@GrpcService class HelloGrpcService : HelloGrpc { // 自定义分块大小,可根据网络和内存情况调整,示例为64KB private val CHUNK_SIZE = 64 * 1024 override fun source(request: Empty?): Multi<SourceResponse> { val file = File("/Users/developer/Downloads/Archive.zip") // 使用resource管理输入流生命周期,自动处理开闭 return Multi.createFrom().resource( { file.inputStream().buffered() }, { inputStream -> Multi.createFrom().generator { emitter -> val buffer = ByteArray(CHUNK_SIZE) var bytesRead: Int // 循环读取文件块,直到流结束 while (inputStream.read(buffer).also { bytesRead = it } != -1) { val chunkData = ByteString.copyFrom(buffer, 0, bytesRead) emitter.emit(SourceResponse.newBuilder().setData(chunkData).build()) } emitter.complete() } }, { inputStream -> inputStream.close() } ) } }
关键说明
- 分块读取:通过固定大小的字节数组每次读取部分文件内容,避免一次性加载整个大文件到内存。
- 资源管理:使用
Multi.createFrom().resource()确保文件输入流在传输完成后自动关闭,防止资源泄漏。 - 流式响应:每读取一个文件块就生成一个
SourceResponse并发送,GRPC会自动将这些响应流式传递给客户端。
你的proto文件已经正确定义了流式返回的RPC方法,无需修改。
内容的提问来源于stack exchange,提问作者softshipper
相关产品推荐
相关产品推荐

