如何用Google Apps Script获取OneDrive公开文件夹的文件JSON
我的个人OneDrive账户有一个公开文件夹,链接格式为https://1drv.ms/f/c/{driveId}/{hereThereIsALongIdWithNumbersAndLetters001}(已修改实际ID保护隐私)。在隐身窗口中可正常查看内容,但文件过多时页面会滚动加载。通过浏览器元素检查器发现,网页会发起请求获取文件的JSON数据,请求URL格式为:
https://my.microsoftpersonalcontent.com/_api/v2.0/drives/{driveId}/items/{anotherIdHere}/children?%24top=100&orderby=folder%2Cname&%24expand=thumbnails%2Ctags&select=*%2Cocr%2CwebDavUrl%2CsharepointIds%2CisRestricted%2CcommentSettings%2CspecialFolder%2CcontainingDrivePolicyScenarioViewpoint&ump=1
我想在Google Apps Script中用UrlFetchApp.fetch()请求该URL获取JSON,但之前可用的代码现在失效,返回错误:
{ "error": { "code": "unauthenticated", "message": "Unauthenticated" } }
之前的代码是:
var json = JSON.parse(UrlFetchApp.fetch(url).getContentText()).value
我尝试从Chrome的Network标签复制该请求为fetch代码,直接用于UrlFetchApp.fetch(),但出现新错误:
{ "error":{ "code":"corsBypassFailure", "message":"Failed to unpack request: Content-Length is out of range (0)" } }
手动添加从检查器复制的Content-Length头时,又触发错误:
Exception: Attribute provided with invalid value: Header:Content-Length
注意到之前使用的是v1.0 API格式的URL,现在已变更为v2.0格式,推测Microsoft已弃用v1.0 API。我尝试过通过Azure应用注册获取OAuth2令牌,但需要付费订阅,希望找到无需API密钥的解决方法。
方法1:模拟浏览器请求头,添加必要标识
Microsoft的v2.0 API对非浏览器请求可能有验证,需要在UrlFetchApp.fetch()中添加模拟浏览器的请求头,同时避免手动设置Content-Length(Google Apps Script会自动处理这个头)。
示例代码:
function fetchOneDriveFiles() { const apiUrl = "https://my.microsoftpersonalcontent.com/_api/v2.0/drives/{driveId}/items/{anotherIdHere}/children?%24top=100&orderby=folder%2Cname&%24expand=thumbnails%2Ctags&select=*%2Cocr%2CwebDavUrl%2CsharepointIds%2CisRestricted%2CcommentSettings%2CspecialFolder%2CcontainingDrivePolicyScenarioViewpoint&ump=1"; const options = { headers: { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36", "Accept": "application/json;odata.metadata=minimal;odata.streaming=true", "Accept-Language": "en-US,en;q=0.9", "Referer": "https://1drv.ms/f/c/{driveId}/{hereThereIsALongIdWithNumbersAndLetters001}" // 替换为你的公开文件夹链接 }, muteHttpExceptions: true // 方便查看完整响应 }; const response = UrlFetchApp.fetch(apiUrl, options); const responseText = response.getContentText(); console.log(response.getResponseCode()); console.log(responseText); if (response.getResponseCode() === 200) { const jsonData = JSON.parse(responseText); const files = jsonData.value; // 处理文件数据 console.log(files); } }
方法2:提取公开分享的shareId,使用简化的API端点
从公开文件夹链接中提取shareId,使用OneDrive的分享内容API,这个端点对公开分享的资源更友好,不需要额外认证:
- 从你的公开链接
https://1drv.ms/f/c/{driveId}/{shareId}中提取{shareId}部分 - 使用以下API格式请求(需对
shareId进行URL编码)
示例代码:
function fetchPublicShareFiles() { const publicLink = "https://1drv.ms/f/c/{driveId}/{hereThereIsALongIdWithNumbersAndLetters001}"; // 编码分享链接为API要求的格式 const encodedShareLink = encodeURIComponent(publicLink); const apiUrl = `https://api.onedrive.com/v1.0/shares/u!${encodedShareLink}/root/children?$top=100&orderby=folder,name&$expand=thumbnails,tags&select=*`; const options = { headers: { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36" } }; const response = UrlFetchApp.fetch(apiUrl, options); const jsonData = JSON.parse(response.getContentText()); const files = jsonData.value; console.log(files); }
关键注意事项
- 不要手动设置
Content-Length头,Google Apps Script会根据请求内容自动生成,手动设置会触发错误 - 必须添加
User-Agent头,模拟浏览器请求,否则可能被API拦截 - 如果方法1仍然返回未认证,可以尝试从浏览器的请求中复制更多头信息(比如
Cookie),但Cookie可能会过期,需要定期更新
内容的提问来源于stack exchange,提问作者Pion Developer

