☰
Windows-universal-samples 之 FileThumbnails:UWP 文件与文件夹缩略图获取实战指南
2026/9/26 2:57:17 网站建设 项目流程
  • 示例工程

【免费下载链接】Windows-universal-samples

API samples for the Universal Windows Platform.

项目地址:https://gitcode.com/gh_mirrors/wi/Windows-universal-samples
点击查看免费下载

本指南以 Windows-universal-samples 仓库中归档的 File and folder thumbnail sample(archived/FileThumbnails/README.md)为核心,系统讲解如何基于Windows.Storage.FileProperties命名空间为图片、音乐、文档、文件夹以及文件组(File Group)获取合适的缩略图。读完本文,你将掌握GetThumbnailAsync/GetScaledImageAsThumbnailAsync的完整调用链、ThumbnailMode与ThumbnailOptions的选型逻辑,以及缩略图流的正确释放方式,可直接迁移到自己的 UWP 应用中。

示例概览:五个演示任务与关键技术点

该示例通过 6 个独立场景(JavaScript 版位于 archived/FileThumbnails/js),逐一演示了以下任务:

  1. 为图片检索缩略图:让用户通过FileOpenPicker选取图片,按所选视图模式返回缩略图(scenario1.js)。
  2. 为歌曲检索专辑封面作为缩略图:返回音乐文件的内嵌专辑封面,并校验其类型确为ThumbnailType.image(scenario2.js)。
  3. 为文档检索图标作为缩略图:对 Office 文档、PDF、纯文本等返回由系统提供的文档图标(scenario3.js)。
  4. 为文件系统文件夹检索缩略图:使用FolderPicker选取真实文件夹并获取其缩略图(scenario4.js)。
  5. 为文件组检索缩略图:文件组(File Group)是一种虚拟文件夹,组内所有文件共享指定的查询条件,示例按“同年同月”对图片库进行分组并取首个分组的缩略图(scenario5.js)。
  6. 按任意像素尺寸获取缩放后的图片:演示getScaledImageAsThumbnailAsync,可在不修改原图的前提下快速获得任意大小的缩放图(scenario6.js)。

示例明确强调了两条使用边界:

  • 无法为“图片库”本身检索缩略图,因为它是虚拟文件夹;必须选择文件系统中实际包含图片的文件夹。
  • 文件组仅在库(Library)中可用,普通文件夹不保证支持分组查询。

核心 API 解析:缩略图数据模型与调用入口

示例涉及的五个关键 API 全部来自Windows.Storage.FileProperties与Windows.Storage命名空间:

API作用
StorageItemThumbnail表示缩略图的只读流对象,同时携带originalWidth、originalHeight、type等元数据
ThumbnailMode枚举,决定缩略图在何种视图下使用,直接影响系统生成缩略图的方式与尺寸
StorageFile.GetThumbnailAsync为文件获取缩略图(StorageFile 实现IStorageItemProperties)
StorageFolder.GetThumbnailAsync为文件夹获取缩略图(StorageFolder 同样实现该接口)
IStorageItemProperties.GetThumbnailAsync文件、文件夹以及虚拟文件夹通用的接口级调用入口

调用入口统一为:

item.getThumbnailAsync(thumbnailMode, requestedSize, thumbnailOptions)
  • thumbnailMode:必填的ThumbnailMode值,指示缩略图的预期使用场景。
  • requestedSize:以像素为单位的请求尺寸(示例中使用 100 或 200,也支持由用户输入任意值)。
  • thumbnailOptions:可选的ThumbnailOptions标志位组合。

从 scenario1.js 可以看到参数组合的典型写法:

var requestedSize = 200, thumbnailMode = modes[modeSelected], thumbnailOptions = Windows.Storage.FileProperties.ThumbnailOptions.useCurrentScale; if (isFastSelected) { thumbnailOptions |= Windows.Storage.FileProperties.ThumbnailOptions.returnOnlyIfCached; }

其中useCurrentScale表示缩略图按当前显示缩放比例生成;按位或(|=)叠加returnOnlyIfCached后,系统将只返回缓存中已存在的缩略图,不再现场生成——这是“快速缩略图(fast thumbnail)”模式,速度更快但可能质量较低或返回 null。

场景一:为图片检索缩略图

scenario1.html 提供三种视图模式供用户选择,映射关系在 scenario1.js 中定义:

下拉选项ThumbnailMode 值适用场景
Thumbnail for a grid layoutThumbnailMode.picturesView网格布局(如瀑布流照片墙)
Thumbnail for a list layoutThumbnailMode.listView列表布局(如带缩略图的纵向列表)
Thumbnail for a single pictureThumbnailMode.singleItem单张图片的大图查看

核心流程(scenario1.js):

var openpicker = new Windows.Storage.Pickers.FileOpenPicker(); openpicker.fileTypeFilter.replaceAll([".jpg", ".png", ".bmp", ".gif", ".tif"]); openpicker.suggestedStartLocation = Windows.Storage.Pickers.PickerLocationId.picturesLibrary; openpicker.pickSingleFileAsync().done(function (file) { if (file) { file.getThumbnailAsync(thumbnailMode, requestedSize, thumbnailOptions).done(function (thumbnail) { if (thumbnail) { outputResult(file, thumbnail, modeNames[modeSelected], requestedSize); } else if (isFastSelected) { // returnOnlyIfCached 模式下缓存未命中 } else { // 该文件没有可用的缩略图 } }); } });

示例限定图片文件类型为.jpg、.png、.bmp、.gif、.tif,并将选择器的起始位置定位到图片库(PickerLocationId.picturesLibrary)。成功返回后,通过outputResult将缩略图流直接赋给<img>元素:

document.getElementById("picture-thumb-imageHolder").src = URL.createObjectURL(thumbnailImage, { oneTimeOnly: true });

值得注意的细节是:URL.createObjectURL只用于一次性显示(oneTimeOnly: true),并在图片加载完成后立即调用thumbnailImage.close()关闭缩略图流(scenario1.js)。StorageItemThumbnail本质上是IRandomAccessStream,不关闭会造成资源泄漏,这一点在所有场景中保持一致。

场景二:为歌曲检索专辑封面

scenario2.js 使用ThumbnailMode.musicView并以 100 像素为请求尺寸,文件类型限定为.mp3、.wma、.m4a、.aac,选择器起始位置为音乐库:

var requestedSize = 100, thumbnailMode = Windows.Storage.FileProperties.ThumbnailMode.musicView; file.getThumbnailAsync(thumbnailMode, requestedSize).done(function (thumbnail) { if (thumbnail) { // 校验类型确为 image(专辑封面),而非 icon(文件图标回退) if (thumbnail.type === Windows.Storage.FileProperties.ThumbnailType.image) { outputResult(file, thumbnail, "ThumbnailMode.musicView", requestedSize); } else { // 该文件没有提供专辑封面 } } });

这里体现了本示例的一个重要工程实践:系统在无法提供专辑封面时可能回退返回文件图标(ThumbnailType.icon)。通过检查thumbnail.type === ThumbnailType.image,可以确认返回的确实是内嵌专辑封面而不是图标回退,避免将图标误当作专辑封面展示给用户。

场景三:为文档检索图标

scenario3.js 使用ThumbnailMode.documentsView,同样以 100 像素为请求尺寸,覆盖 Office 全系列格式及常见文本文档:

openpicker.fileTypeFilter.replaceAll([".doc", ".xls", ".ppt", ".docx", ".xlsx", ".pptx", ".pdf", ".txt", ".rtf"]); openpicker.suggestedStartLocation = Windows.Storage.Pickers.PickerLocationId.documentsLibrary; file.getThumbnailAsync(thumbnailMode, requestedSize).done(function (thumbnail) { if (thumbnail) { outputResult(file, thumbnail, "ThumbnailMode.documentsView", requestedSize); } else { // 该文档没有可用的图标 } });

对于没有内嵌预览的文档类型,系统通常返回与该文件类型关联的图标作为缩略图。选择器起始位置为文档库(PickerLocationId.documentsLibrary)。

场景四:为文件系统文件夹检索缩略图

文件夹缩略图通过StorageFolder.GetThumbnailAsync获取。scenario4.js 使用FolderPicker让用户挑选一个真实的文件系统文件夹:

var openpicker = new Windows.Storage.Pickers.FolderPicker; openpicker.fileTypeFilter.replaceAll([".jpg", ".png", ".bmp", ".gif", ".tif"]); openpicker.suggestedStartLocation = Windows.Storage.Pickers.PickerLocationId.picturesLibrary; openpicker.pickSingleFolderAsync().done(function (folder) { if (folder) { folder.getThumbnailAsync(thumbnailMode, requestedSize).done(function (thumbnail) { if (thumbnail) { outputResult(folder, thumbnail, "ThumbnailMode.picturesView", requestedSize); } else { // 文件夹中没有可生成缩略图的图片 } }); } });

示例使用ThumbnailMode.picturesView、请求尺寸 200 像素,返回的文件夹缩略图由文件夹内的图片合成。README 特别提醒:不能为图片库本身(Pictures library)检索缩略图,因为它是虚拟文件夹,只能选取文件系统中实际存放图片的文件夹。

场景五:为文件组(File Group)检索缩略图

文件组是Windows.Storage.Search提供的虚拟文件夹机制:组内所有文件共享调用方指定的公共条件。scenario5.js 使用CommonFolderQuery.groupByMonth按“同年同月”对图片进行分组,完整调用链如下:

var monthShape = Windows.Storage.Search.CommonFolderQuery.groupByMonth; // 1. 先确认所选文件夹(库)支持该分组查询 if (folder.isCommonFolderQuerySupported(monthShape)) { // 2. 将文件夹转换为分组查询并取得各组(虚拟文件夹) var query = folder.createFolderQuery(monthShape); query.getFoldersAsync().done(function (monthList) { if (monthList && monthList.size > 0) { var firstMonth = monthList.getAt(0); // 3. 对第一个分组调用与普通文件夹相同的缩略图 API firstMonth.getThumbnailAsync(thumbnailMode, requestedSize).done(function (thumbnail) { if (thumbnail) { outputResult(firstMonth, thumbnail, "ThumbnailMode.picturesView", requestedSize, true); } }); // 4. 同时枚举该分组内的文件列表 firstMonth.getFilesAsync().done(function (files) { files.forEach(function (file) { outputHeader(file.name); }); }); } }); }

这段代码展示了三条关键事实:

  • 分组查询的入口是isCommonFolderQuerySupported(commonFolderQuery)与createFolderQuery(commonFolderQuery),二者均来自StorageFolder。
  • 文件组只在库中生效:示例通过isCommonFolderQuerySupported预检,若所选文件夹不是库或图片库中没有满足分组条件的文件,则分别提示错误(SdkSample.errors.filegroupLocation/emptyFilegroup)。
  • 分组结果(monthList)中的每一项都是虚拟文件夹,仍然可以复用GetThumbnailAsync获取代表该组的缩略图。

场景六:按任意尺寸获取缩放图片

scenario6.js 演示了getScaledImageAsThumbnailAsync:允许用户在界面中输入任意像素尺寸,系统在尽可能快的前提下返回该尺寸的缩放图(某些情况下会借助云服务获取缩略图)。

var requestedSize = parseInt(document.getElementById("picture-thumb-requestSize").value); if (requestedSize > 0 && !isNaN(requestedSize)) { var thumbnailMode = Windows.Storage.FileProperties.ThumbnailMode.singleItem, thumbnailOptions = Windows.Storage.FileProperties.ThumbnailOptions.useCurrentScale; if (isFastSelected) { thumbnailOptions |= Windows.Storage.FileProperties.ThumbnailOptions.returnOnlyIfCached; } file.getScaledImageAsThumbnailAsync(thumbnailMode, requestedSize, thumbnailOptions).done(function (thumbnail) { if (thumbnail) { outputResult(file, thumbnail, "ThumbnailMode.singleItem", requestedSize); } }); } else { // 输入尺寸非法(<=0 或非数字) }

与GetThumbnailAsync相比,该 API 更贴合“按需缩放”场景:入参不是期望的请求尺寸上限,而是目标像素值;同时保留了useCurrentScale与returnOnlyIfCached的组合能力。示例同时对用户输入做了合法性校验(requestedSize > 0 && !isNaN(requestedSize)),非法输入直接提示错误。

通用输出与资源释放模式

六个场景共用同一套输出模式,体现了处理StorageItemThumbnail流的推荐做法(以 scenario1.js 为例):

function outputResult(item, thumbnailImage, thumbnailMode, requestedSize) { // 1. 将缩略图流绑定到 <img>,一次性使用 document.getElementById("picture-thumb-imageHolder").src = URL.createObjectURL(thumbnailImage, { oneTimeOnly: true }); // 2. 图片渲染完成后立即关闭流,释放底层资源 document.getElementById("picture-thumb-imageHolder").onload = function () { thumbnailImage.close(); }; // 3. 展示元数据:模式、文件名、请求尺寸、实际返回尺寸 document.getElementById("picture-thumb-modeName").innerText = thumbnailMode; document.getElementById("picture-thumb-fileName").innerText = "File used: " + item.name; document.getElementById("picture-thumb-requestedSize").innerText = "Requested size: " + requestedSize; document.getElementById("picture-thumb-returnedSize").innerText = "Returned size: " + thumbnailImage.originalWidth + "x" + thumbnailImage.originalHeight; }

三个要点:

  1. 流绑定:URL.createObjectURL可将StorageItemThumbnail(IRandomAccessStream)直接作为图片源。
  2. 主动关闭:thumbnailImage.close()在onload回调中执行,避免流长期占用资源;重复操作前还会调用cleanOutput()清空上一次的输出与状态。
  3. 尺寸核对:通过originalWidth/originalHeight展示系统实际返回的缩略图尺寸,可与请求尺寸对照,便于理解不同ThumbnailMode下的缩放行为。

构建与运行环境

依据 archived/FileThumbnails/README.md 的说明:

  • 工具链:需要 Visual Studio 2017 构建,Windows 10 上执行(JavaScript 工程文件为 FileThumbnails.jsproj,解决方案为 FileThumbnails.sln)。
  • 系统要求:客户端 Windows 10、服务端 Windows Server 2016 Technical Preview、移动端 Windows 10。

构建步骤:

  1. 若以 ZIP 方式下载示例集合,需解压整个压缩包(而非只解压单个示例目录),以便共享依赖正常工作。
  2. 启动 Visual Studio 2017,选择File>Open>Project/Solution。
  3. 进入Samples子目录下的对应示例目录,选择目标语言子目录(C++、C# 或 JavaScript),双击其中的.sln文件。
  4. 按Ctrl+Shift+B或选择Build>Build Solution完成编译。

运行与部署:

  • 仅部署:选择Build>Deploy Solution。
  • 调试运行:按F5或选择Debug>Start Debugging。
  • 免调试运行:按Ctrl+F5或选择Debug>Start Without Debugging。

相关主题与延伸学习

README 将本示例归类为 UWP 文件访问能力的一部分,仓库内与之关联的样本可继续深入:

  • File access sample:文件读写与基本存储操作
  • File picker sample:文件/文件夹选择器完整用法
  • Folder enumeration sample:文件夹枚举与查询
  • Programmatic file search sample:基于查询语法(AQS)的编程式文件搜索

以上样本在仓库中同时提供 C++/C++/WinRT/C# 等多种语言实现(部分归档于 archived 目录),可与本文的 JavaScript 实现相互对照。若需设计“向用户展示恰当缩略图”的交互,官方指南强调应依据缩略图的最终展示上下文(网格、列表、单图、文档、音乐等)选择对应的ThumbnailMode,并结合ThumbnailOptions.returnOnlyIfCached在速度与质量之间做权衡——这正是本示例六个场景反复演示的核心决策模型。

  • 示例工程

【免费下载链接】Windows-universal-samples

API samples for the Universal Windows Platform.

项目地址:https://gitcode.com/gh_mirrors/wi/Windows-universal-samples
点击查看免费下载
上一篇:专业级.NET逆向工程:5个高效策略深度解析dnSpy调试器
下一篇:如何轻松实现Windows和Office永久激活:终极免费解决方案指南

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询