如何使用JAVA下载Azure Blob存储容器根目录及子文件夹下的所有文件
报错原因
你遇到的类型转换异常,是因为listBlobs()默认返回的ListBlobItem集合包含两类对象:
- 实际存储的文件对应的
CloudBlockBlob实例 - 容器内的虚拟目录对应的
CloudBlobDirectory实例
直接把所有返回项强转为CloudBlockBlob,遇到目录项时就会抛出该异常。
实现全容器文件下载的解决方案
有两种常用实现方式,都可以兼容根目录和多层子目录的文件下载,同时避免类型转换错误:
方案1:使用扁平化遍历(更简洁)
调用listBlobs的重载方法,开启扁平化遍历开关,直接返回容器内所有层级的Blob文件,不会返回目录项,无需额外递归处理目录:
CloudBlobContainer cloudBlobContainer = StorageAccount(azureStorageProperties,clientCredential).createCloudBlobClient() .getContainerReference(container); System.out.println("Access " + container + " container successful. Now start to download the file."); // 第二个参数useFlatBlobListing设为true,开启全容器扁平化遍历,返回所有层级的Blob文件 Iterable<ListBlobItem> blobs = cloudBlobContainer.listBlobs(null, true, EnumSet.noneOf(BlobListingDetails.class), null, null); for (ListBlobItem blob : blobs) { // 增加类型判断,规避其他类型Blob导致的转换异常 if (blob instanceof CloudBlockBlob) { CloudBlockBlob cloudBlob = (CloudBlockBlob) blob; // 自动创建本地对应子目录,避免下载子目录文件时因本地路径不存在报错 File localFile = new File(inputPath + "/" + cloudBlob.getName()); localFile.getParentFile().mkdirs(); cloudBlob.downloadToFile(localFile.getAbsolutePath()); } }
方案2:递归遍历目录
如果需要单独处理目录逻辑,可以用递归方式逐个判断项类型,遇到目录就继续遍历下一层,遇到文件就执行下载:
// 递归遍历Blob项并下载的工具方法 private void traverseAndDownload(ListBlobItem item, String localRootPath) throws Exception { if (item instanceof CloudBlockBlob) { CloudBlockBlob blob = (CloudBlockBlob) item; File localFile = new File(localRootPath + "/" + blob.getName()); localFile.getParentFile().mkdirs(); blob.downloadToFile(localFile.getAbsolutePath()); } else if (item instanceof CloudBlobDirectory) { // 遇到目录则遍历目录下的所有子项 CloudBlobDirectory dir = (CloudBlobDirectory) item; for (ListBlobItem subItem : dir.listBlobs()) { traverseAndDownload(subItem, localRootPath); } } } // 主逻辑调用 CloudBlobContainer cloudBlobContainer = StorageAccount(azureStorageProperties,clientCredential).createCloudBlobClient() .getContainerReference(container); System.out.println("Access " + container + " container successful. Now start to download the file."); Iterable<ListBlobItem> rootItems = cloudBlobContainer.listBlobs(); for (ListBlobItem item : rootItems) { traverseAndDownload(item, inputPath); }
内容的提问来源于stack exchange,提问作者Bing Hao
相关产品推荐
相关产品推荐

