在JavaScript中下载OneDrive跨域资源共享(CORS)文件

8
我正在尝试使用客户端JavaScript处理OneDrive文件,但首先需要一种使用XMLHttpRequest下载文件的方法。 OneDrive支持许多操作的cors,但是对于将文件下载到JavaScript中,存在以下问题:
onedrive rest api manual所述,
我可以发送请求到:
GET https://apis.live.net/v5.0/FILE_ID/content?access_token=ACCESS_TOKEN 它会回复一个位置头重定向浏览器到该文件。 问题是当我通过XHR发送这些请求时,浏览器总是发送Origin标头与请求一起发送。 对于我上面描述的第一个请求,OneDrive还会回复Access-Control-Allow-Origin:*标头,因此在浏览器中允许该请求。 然而,当浏览器被重定向到文件的实际位置时,该资源没有Access-Control-Allow-Origin标头,因此XHR请求被浏览器拒绝(chrome为重定向请求设置了null Origin标头)。
我还尝试过获取位置但不自动重定向,然后发送另一个XHR请求,这将把原始标头设置为我的站点域,但结果相同。正如我在开头提到的,我需要在javascript中处理数据,所以我不是在询问如何将onedrive文件下载到硬盘。我需要javascript在网页中访问该数据。
我知道我可以使用服务器端编程来获取文件数据并将其发送到客户端,但对于我的应用程序,这不是一个选项(至少目前不是我要求的内容)。
如果没有办法做到这一点,是否有人知道为什么他们会以这种方式实现他们的api?允许javascript通过cors获取位置并重定向,但不包括重定向资源的cors标头。为什么不一开始就拒绝cors?这是一个错误吗?
4个回答

5
据我所知,仅通过浏览器中的JavaScript无法下载内容。他们为什么这样做?你需要问他们,但我猜想可能是出于错误或某些未指定的“安全问题”。就它的价值而言,在此处文档中,他们似乎认为下载内容符合CORS:https://dev.onedrive.com/misc/working-with-cors.htm

在JavaScript应用程序中从OneDrive下载文件,不能使用/content API,因为该API响应一个302重定向。当需要进行CORS预检时,如提供Authorization标头时,禁止显式使用302重定向。

相反,您的应用程序需要选择@content.downloadUrl属性,该属性返回与/content将要重定向到的相同URL。然后,可以直接使用XMLHttpRequest请求此URL。由于这些URL已经过身份验证,因此可以在不需要CORS预检请求的情况下检索它们。

但据我所知,他们是错的。仅因为您不需要预检请求并不意味着响应符合CORS。仍然需要响应中的Access-Control-Allow-Origin标头。
对于任何想了解的人,这个问题在新的Graph API中仍然存在(据我所理解,这本质上是OneDrive API的代理API)。同样的基本问题仍然存在-您可以从项目中获取下载URL,但该URL指向不符合CORS的资源,因此没有什么帮助。
我在Microsoft这里提出了一个活动问题here。对我的问题有一些回应(我让他们通过图形API公开了下载URL),但我仍在等待看看他们是否会想出从JavaScript下载内容的真正解决方案。
如果我在那个问题上得到解决方案或真正的答案,我将尝试在这里报告,以便未来的其他人可以有一个真正的参考答案。

4

这不是一个答案,我暂时还不能发表评论。

上周发布了OneDrive的新API。 http://onedrive.github.io/index.htm

但不幸的是,它并不能解决问题。

https://api.onedrive.com/v1.0/drive/root:{path and name}:/content?access_token={token}

仍将重定向到某个资源,位于https://X.files.1drv.com/.X.

该资源不会包含任何Access-Control-Allow-Origin头。JSON响应中的Url "@content.downloadUrl"也是如此。

我希望微软能够在不久的将来解决这个问题,因为API目前的使用非常有限,由于无法使用html5应用程序处理来自onedrive的文件内容。除了通常的文件浏览器之外。

目前唯一的解决方案是使用可以处理没有CORS的Url的Chrome应用程序,请参见https://developer.chrome.com/apps/angular_framework


我可以确认你的回复...在浏览器中,似乎没有办法从JavaScript应用程序中下载文件。下载URL没有CORS支持。 - yegodz
微软?有人在吗...你能评论一下OneDrive API如何支持CORS吗?现在我可以从我的单页应用程序进行身份验证、创建和删除文件,但无法下载!?这似乎不是声称支持CORS的方式。 - yegodz
我目前正在将OneDrive与我们的服务集成,但老实说,我已经快要决定完全放弃对它的支持了。我们必须通过自己的服务器路由数据,这既昂贵,又不利于隐私和安全。严重的是,整整一年过去了,他们什么也没做来解决这样一个简单却致命的问题。 - user1419305
然而,可能最糟糕的是微软对这些问题的批评反应方式,他们坚持自己的立场并声称一切都很好,直到被证明错误。之后,他们只是停止回应而不是真正解决任何问题。 - user1419305

1
Box对于下载请求的处理方式与此完全相同。我没有找到任何绕过此问题的方法,除非涉及服务器,因为浏览器不允许程序获取302重定向响应的内容。出于某种我不确定的安全原因,浏览器强制执行重定向请求,而不允许用户干预。
我们最终解决这个问题的方法是:
  1. 浏览器应用程序向服务器发送GET请求,服务器将其转发到云提供商(box/ondrive)。
  2. 然后,服务器不会遵循来自Box或OneDrive的302重定向响应。
  3. 服务器会返回包含下载URL的302响应头中的location字段的内容给浏览器应用程序。
  4. 然后,浏览器应用程序中的JavaScript使用该URL下载文件。

我刚刚检查了一下...请看下面我的评论。这种方法在OneDrive上不起作用(至少现在还不行)。CORS下载是不受支持的。 - yegodz

1
您现在可以在GET请求中使用项目的“@content.downloadUrl”属性,这样就不需要重定向了。
来自https://dev.onedrive.com/items/download.htm

返回302 Found响应,将重定向到文件的预身份验证下载URL。这是通过项目上的@content.downloadUrl属性可用的相同URL。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接