Google Drive API分页异常:仅两页时上页正常,多页失效
问题分析与解决方案
问题根源
- 原上一页逻辑错误:点击上一页时直接调用
listFiles(folderId)(不传pageToken),仅适用于从第2页返回第1页的场景。当页数超过2页时,从第3页返回第2页需要传入第2页对应的pageToken(即第1页的nextPageToken),而非直接传null,这导致回到第2页后无法继续返回第1页。 - 令牌数组未正确维护:尝试用数组存储令牌时,没有跟踪当前页面在历史中的位置,导致后退时无法正确匹配对应的上一页令牌。
解决方案:维护分页历史栈
通过维护一个页面令牌历史栈和当前页面索引,精准控制前后翻页的令牌传递:
1. 初始化全局状态变量
// 存储所有访问过的页面令牌,索引0对应第1页(token为null) let pageTokenHistory = [null]; // 当前页面在历史栈中的索引,初始为第1页 let currentPageIndex = 0;
2. 修改listFiles函数的翻页逻辑
async function listFiles(folderId, pageToken = null) { $('#table_content').empty(); $('#table_content').remove(); isListFilesInProgress = true; $('#show_files_button').prop('disabled', true); const request = { q: `'${folderId}' in parents`, pageSize: 10, fields: 'nextPageToken, files(id, name, mimeType, thumbnailLink, webContentLink, modifiedTime)', pageToken: pageToken, }; gapi.client.drive.files .list(request) .then(function (response) { console.log(response); var files = response.result.files; if (files && files.length > 0) { // 生成表格的代码保持不变,此处省略重复代码 var table = document.createElement('table'); table.classList.add('table', 'table-striped'); table.id = 'table_content'; var thead = document.createElement('thead'); var headerRow = document.createElement('tr'); var header1 = document.createElement('th'); header1.textContent = 'Thumbnail'; var header2 = createSortableHeader('Name', 'name'); var header3 = createSortableHeader('Type', 'mimeType'); var header4 = createSortableHeader('Last Updated', 'modifiedTime'); var header5 = document.createElement('th'); header5.textContent = 'Download'; headerRow.appendChild(header1); headerRow.appendChild(header2); headerRow.appendChild(header3); headerRow.appendChild(header4); headerRow.appendChild(header5); thead.appendChild(headerRow); table.appendChild(thead); var tbody = document.createElement('tbody'); for (var i = 0; i < files.length; i++) { (function (file) { var fileName = file.name; var mimeType = file.mimeType; var thumbnailLink = file.thumbnailLink; var downloadLink = file.webContentLink; var lastUpdated = new Date(file.modifiedTime).toLocaleString(); var fileId = file.id; var row = document.createElement('tr'); var thumbnailCell = createThumbnailCell(thumbnailLink, mimeType, fileId); row.appendChild(thumbnailCell); var nameCell = document.createElement('td'); nameCell.textContent = fileName; row.appendChild(nameCell); var typeCell = document.createElement('td'); typeCell.textContent = mimeType; row.appendChild(typeCell); var lastUpdatedCell = document.createElement('td'); lastUpdatedCell.textContent = lastUpdated; row.appendChild(lastUpdatedCell); if (mimeType != 'application/vnd.google-apps.folder') { var downloadCell = document.createElement('td'); var downloadLinkElem = document.createElement('a'); downloadLinkElem.href = downloadLink; downloadLinkElem.textContent = 'Download'; downloadLinkElem.classList.add('btn', 'btn-primary'); downloadLinkElem.target = '_blank'; downloadCell.appendChild(downloadLinkElem); row.appendChild(downloadCell); } if (mimeType === 'application/vnd.google-apps.folder') { row.classList.add('folder-row'); row.addEventListener('click', function () { var folderId = file.id; // 进入新文件夹时重置分页历史 pageTokenHistory = [null]; currentPageIndex = 0; listFiles(folderId); }); } tbody.appendChild(row); })(files[i]); } table.appendChild(tbody); document.getElementById('content').appendChild(table); // 移除旧的翻页按钮 $('.next-page-button').remove(); $('.previous-page-button').remove(); const nextPageToken = response.result.nextPageToken; // 添加下一页按钮 if (nextPageToken) { const nextPageButton = document.createElement('button'); nextPageButton.textContent = 'Next Page'; nextPageButton.classList.add('btn', 'btn-primary', 'next-page-button'); nextPageButton.addEventListener('click', function () { // 若当前是历史栈最后一页,将新令牌加入栈 if (currentPageIndex === pageTokenHistory.length - 1) { pageTokenHistory.push(nextPageToken); } currentPageIndex++; listFiles(folderId, nextPageToken); }); document.getElementById('content').appendChild(nextPageButton); } // 添加上一页按钮:仅当前索引大于0时显示(非第一页) if (currentPageIndex > 0) { const previousPageButton = document.createElement('button'); previousPageButton.textContent = 'Previous Page'; previousPageButton.classList.add('btn', 'btn-primary', 'previous-page-button'); previousPageButton.addEventListener('click', function () { currentPageIndex--; // 从历史栈中取出上一页的令牌 const prevToken = pageTokenHistory[currentPageIndex]; listFiles(folderId, prevToken); }); document.getElementById('content').appendChild(previousPageButton); } } }) .finally(function () { isListFilesInProgress = false; $('#show_files_button').prop('disabled', false); }); }
3. 关键修改说明
- 历史栈维护:点击下一页时,若当前是历史栈的最后一页,将新的
nextPageToken加入栈;若从中间页前进(如从第2页回到第3页),直接使用栈中已有的令牌。 - 上一页逻辑:点击上一页时,将当前索引减1,从历史栈中取出对应索引的令牌,确保回到正确的上一页。
- 文件夹导航重置:进入新文件夹时重置历史栈和索引,避免不同文件夹的分页令牌混淆。
内容的提问来源于stack exchange,提问作者Laimonas Rupeika
相关产品推荐
相关产品推荐

