使用camel-azure-storage-blob出现StorageInputStream流已关闭报错求解决
问题根因
Camel从Azure Blob消费到的消息体默认是BlobInputStream类型,属于一次性只读流。你在.to(myapiendpoint)调用第三方接口的过程中,这个流已经被读取消费并自动关闭了,后续异常分支里不管是执行.convertBodyTo(byte[].class)还是直接上传到错误容器,尝试二次读取已关闭的流就会触发该报错。
解决方案
方案1:消费到Blob后立即将流缓存为字节数组,放在Exchange属性中备用
调整路由逻辑,在流还未被消费时就完成转储,后续分支直接使用缓存的内容即可,路由配置参考:from(azurebloburi) // 第一步就将流转换为字节数组缓存,避免流被消费后无法二次读取 .convertBodyTo(byte[].class) // 将原始字节数组存到Exchange属性里,后续所有分支通用 .setProperty("originalBlobContent", body()) .process(getHeaders()) .log(LoggingLevel.INFO, log, "After adding Headers =${in.headers})") .doTry() .to(myapiendpoint) .process(moveTheFile(SUCCESS_CONTAINER)) // 成功分支直接复用缓存的字节数组上传 .setBody(exchangeProperty("originalBlobContent")) .toD(mysuccesscontaineruri-azure) .doCatch(Exception.class) .log(LoggingLevel.ERROR, log, "Exception - Moving into ERROR.") .process(moveTheFile(ERROR_CONTAINER)) // 异常分支也直接复用缓存的字节数组,不需要读取原始流 .setBody(exchangeProperty("originalBlobContent")) .toD(myerrorcontainer-azure) .end()方案2:调整消费端配置,直接获取字节数组而非流
在camel-azure-storage-blob的消费URI中新增参数blobOutputType=bytearray,配置示例:azure-storage-blob://<账号名>/<容器名>?blobOutputType=bytearray&其他原有参数
配置完成后消费到的消息体默认就是字节数组类型,不存在流关闭问题,无需额外做缓存处理。方案3:大文件场景下使用copyBlob接口实现迁移,无需读取文件内容
如果待迁移的文件体积较大,缓存字节数组会占用过高内存,可以直接调用Azure的copyBlob原生接口完成容器间文件迁移,不需要读取文件内容,自然不会涉及流读取问题,请求头配置调整参考:exchange.getIn().setHeader(BlobConstants.BLOB_OPERATION, BlobOperationsDefinition.copyBlob); // 填写原始Blob的完整访问URI作为复制源 exchange.getIn().setHeader(BlobConstants.SOURCE_BLOB_URI, "原始Blob的访问URI"); exchange.getIn().setHeader(BlobConstants.BLOB_NAME, "目标Blob名称");
内容的提问来源于stack exchange,提问作者JDGuide
相关产品推荐
相关产品推荐

