I am able to generate public URLs for iCloud files. e.g. https://www.icloud.com/documents/dl/?p=3&t=BAKsXkcDP-p8sdTS8NgBLWRQxE281oe4hogA
Accessing such a URL from a browser, I see a landing page, and shorty afterwards the file downloads automatically. Fine.
However, I want to be able to download this file from my iOS app (with NSURLConnection). How can I do this? Maybe... a) process the html headers to somehow determine the direct URL? b) intercept the redirect/refresh that triggers the download on a browser? c) somehow imitate a browser in order to trigger a download?
Thanks
PS. please give me the idiot's answer- I'm clueless about html etc.
Here is the html response I'm getting for the indirect URL above:
var SC_benchmarkPreloadEvents={headStart:new Date().getTime()}; -->iCloud - Loading ...window.SC=window.SC||{MODULE_INFO:{},LAZY_INSTANTIATION:{}};SC.buildMode="production"; SC.buildNumber="1FCS22.32292";SC.buildLocale="en-us";String.preferredLanguage="en-us";window.SC=window.SC||{MODULE_INFO:{},LAZY_INSTANTIATION:{}};SC._detectBrowser=function(userAgent,language){var version,webkitVersion,browser={}; userAgent=(userAgent||navigator.userAgent).toLowerCase();language=language||navigator.language||navigator.browserLanguage; version=browser.version=(userAgent.match(/.*(?:rv|chrome|webkit|opera|ie)/: ([ );]|$)/)||[])[1]; webkitVersion=(userAgent.match(/webkit/(.+?) /)||[])[1];browser.windows=browser.isWindows=!!/windows/.test(userAgent); browser.mac=browser.isMac=!!/macintosh/.test(userAgent)||(/mac os x/.test(userAgent)&&!/like mac os x/.test(userAgent)); browser.lion=browser.isLion=!!(/mac os x 10_7/.test(userAgent)&&!/like mac os x 10_7/.test(userAgent)); browser.iPhone=browser.isiPhone=!!/iphone/.test(userAgent);browser.iPod=browser.isiPod=!!/ipod/.test(userAgent); browser.iPad=browser.isiPad=!!/ipad/.test(userAgent);browser.iOS=browser.isiOS=browser.iPhone||browser.iPod||browser.iPad; browser.android=browser.isAndroid=!!/android/.test(userAgent);browser.opera=/opera/.test(userAgent)?version:0; browser.isOpera=!!browser.opera;browser.msie=/msie/.test(userAgent)&&!browser.opera?version:0; browser.isIE=!!browser.msie;browser.isIE8OrLower=!!(browser.msie&&parseInt(browser.msie,10)<=8); browser.mozilla=/mozilla/.test(userAgent)&&!/(compatible|webkit|msie)/.test(userAgent)?version:0; browser.isMozilla=!!browser.mozilla;browser.webkit=/webkit/.test(userAgent)?webkitVersion:0; browser.isWebkit=!!browser.webkit;browser.chrome=/chrome/.test(userAgent)?version:0; browser.isChrome=!!browser.chrome;browser.mobileSafari=/apple.*mobile/.test(userAgent)&&browser.iOS?webkitVersion:0; browser.isMobileSafari=!!browser.mobileSafari;browser.iPadSafari=browser.iPad&&browser.isMobileSafari?webkitVersion:0; browser.isiPadSafari=!!browser.iPadSafari;browser.iPhoneSafari=browser.iPhone&&browser.isMobileSafari?webkitVersion:0; browser.isiPhoneSafari=!!browser.iphoneSafari;browser.iPodSafari=browser.iPod&&browser.isMobileSafari?webkitVersion:0; browser.isiPodSafari=!!browser.iPodSafari;browser.isiOSHomeScreen=browser.isMobileSafari&&!/apple.*mobile.*safari/.test(userAgent); browser.safari=browser.webkit&&!browser.chrome&&!browser.iOS&&!browser.android?webkitVersion:0; browser.isSafari=!!browser.safari;browser.language=language.split("-",1)[0];browser.current=browser.msie?"msie":browser.mozilla?"mozilla":browser.chrome?"chrome":browser.safari?"safari":browser.opera?"opera":browser.mobileSafari?"mobile-safari":browser.android?"android":"unknown"; return browser};SC.browser=SC._detectBrowser();if(typeof SC_benchmarkPreloadEvents!=="undefined"){SC.benchmarkPreloadEvents=SC_benchmarkPreloadEvents; SC_benchmarkPreloadEvents=undefined}else{SC.benchmarkPreloadEvents={headStart:new Date().getTime()} }SC.setupBodyClassNames=function(){var el=document.body;if(!el){return}var browser,platform,shadows,borderRad,classNames,style; browser=SC.browser.current;platform=SC.browser.windows?"windows":SC.browser.mac?"mac":"other-platform"; style=document.documentElement.style;shadows=(style.MozBoxShadow!==undefined)||(style.webkitBoxShadow!==undefined)||(style.oBoxShadow!==undefined)||(style.boxShadow!==undefined); borderRad=(style.MozBorderRadius!==undefined)||(style.webkitBorderRadius!==undefined)||(style.oBorderRadius!==undefined)||(style.borderRadius!==undefined); classNames=el.className?el.className.split(" "):[];if(shadows){classNames.push("box-shadow") }if(borderRad){classNames.push("border-rad")}classNames.push(browser);if(browser==="chrome"){classNames.push("safari") }classNames.push(platform);var ieVersion=parseInt(SC.browser.msie,10);if(ieVersion){if(ieVersion===7){classNames.push("ie7") }else{if(ieVersion===8){classNames.push("ie8")}else{if(ieVersion===9){classNames.push("ie9") }}}}if(SC.browser.mobileSafari){classNames.push("mobile-safari")}if("createTouch" in document){classNames.push("touch") }el.className=classNames.join(" ")};(function(){var styles=[];if(window.devicePixelRatio==2||window.location.search.indexOf("2x")>-1){styles=["/applications/documents/download/en-us/1FCS22.32292/[email protected]"]; SC.APP_IMAGE_ASSETS=["/applications/documents/sproutcore/desktop/en-us/1FCS22.32292/[email protected]","/applications/documents/coreweb/views/en-us/1FCS22.32292/[email protected]","/applications/documents/sproutcore/ace/en-us/1FCS22.32292/[email protected]","/applications/documents/sproutcore/ace/en-us/1FCS22.32292/[email protected]","/applications/documents/sproutcore/ace/en-us/1FCS22.32292/[email protected]","/applications/documents/download/en-us/1FCS22.32292/[email protected]","/applications/documents/download/en-us/1FCS22.32292/[email protected]"] }else{styles=["/applications/documents/download/en-us/1FCS22.32292/stylesheet-packed.css"]; SC.APP_IMAGE_ASSETS=["/applications/documents/sproutcore/desktop/en-us/1FCS22.32292/stylesheet-no-repeat.png","/applications/documents/coreweb/views/en-us/1FCS22.32292/stylesheet-no-repeat.png","/applications/documents/sproutcore/ace/en-us/1FCS22.32292/stylesheet-no-repeat.png","/applications/documents/sproutcore/ace/en-us/1FCS22.32292/stylesheet-repeat-x.png","/applications/documents/sproutcore/ace/en-us/1FCS22.32292/stylesheet-repeat-y.png","/applications/documents/download/en-us/1FCS22.32292/stylesheet-no-repeat.png","/applications/documents/download/en-us/1FCS22.32292/stylesheet-repeat-x.png"] }var head=document.getElementsByTagName("head")[0],len=styles.length,idx,css;for(idx=0; idxSC.benchmarkPreloadEvents.headEnd=new Date().getTime();SC.benchmarkPreloadEvents.bodyStart=new Date().getTime();if(SC.setupBodyClassNames){SC.setupBodyClassNames()};SC.benchmarkPreloadEvents.bodyEnd=new Date().getTime();
As of July 2012, the following seems to work. But there's no guarantee that apple won't change their scheme for generating these, and it's possible that they would regard this as a private API and reject your app. So use at your own risk.
The URL has two important parameters, p
and t
. The first seems to identify a server, while the second identifies the actual file. The direct download link is made by plugging these values into this URL:
https://p[p]-ubiquityws.icloud.com/ws/file/[t]
Looking at your example:
https://www.icloud.com/documents/dl/?p=3&t=BAKsXkcDP-p8sdTS8NgBLWRQxE281oe4hogA
p
is 3
, and t
is BAKsXkcDP-p8sdTS8NgBLWRQxE281oe4hogA
. So your direct download link would be
https://p3-ubiquityws.icloud.com/ws/file/BAKsXkcDP-p8sdTS8NgBLWRQxE281oe4hogA
Whenever I've published a link to iCloud, p
has been 01
; so it's possible that you might need to zero-pad your value in which case your URL would be
https://p03-ubiquityws.icloud.com/ws/file/BAKsXkcDP-p8sdTS8NgBLWRQxE281oe4hogA
It would be great to know whether that's necessary.
In iCloud Drive / iOS8 the links are different, but you can still get a direct link to the files.
Original link:
https://www.icloud.com/attachment?u=https%3A%2F%2Fms-eu-ams-103-prod.digitalhub.com%2FB%2FATmkKK8ju8SRwQqDoEFKJzbRsxiuAXQ3PBcJBXw1Qot9jz68TkqjiiNu%2F%24%7Bf%7D%3Fo%3DAtenENR8OcvlNq6JMa331mr-8gCreXxwcfgQ26B5gFKo%26v%3D1%26x%3D3%26a%3DBclucinSeKmFAy2GJg%26e%3D1413787013%26k%3D%24%7Buk%7D%26r%3D567CC38A-FD1B-4DE6-B11B-4166A5669E1B-1%26z%3Dhttps%253A%252F%252Fp03-content.icloud.com%253A443%26s%3DlO5SolOouS9qhYz1oIxKDoGtMpo%26hs%3DovfPXj3b9XXz9lWKChBmyNq_cug&uk=OXDCcLTETbvUcOKdJ-vTdQ&f=Testdatei.vrphoto&sz=1212622
URL decoded to be more readable:
https://www.icloud.com/attachment?u=https://ms-eu-ams-103-prod.digitalhub.com/B/ATmkKK8ju8SRwQqDoEFKJzbRsxiuAXQ3PBcJBXw1Qot9jz68TkqjiiNu/${f}?o=AtenENR8OcvlNq6JMa331mr-8gCreXxwcfgQ26B5gFKo&v=1&x=3&a=BclucinSeKmFAy2GJg&e=1413787013&k=${uk}&r=567CC38A-FD1B-4DE6-B11B-4166A5669E1B-1&z=https%3A%2F%2Fp03-content.icloud.com%3A443&s=lO5SolOouS9qhYz1oIxKDoGtMpo&hs=ovfPXj3b9XXz9lWKChBmyNq_cug&uk=OXDCcLTETbvUcOKdJ-vTdQ&f=Testdatei.vrphoto&sz=1212622
Voila, here is your direct link to the file:
https://ms-eu-ams-103-prod.digitalhub.com/B/ATmkKK8ju8SRwQqDoEFKJzbRsxiuAXQ3PBcJBXw1Qot9jz68TkqjiiNu/Testdatei.vrphoto?o=AtenENR8OcvlNq6JMa331mr-8gCreXxwcfgQ26B5gFKo&v=1&x=3&a=BclucinSeKmFAy2GJg&e=1413787013&k=OXDCcLTETbvUcOKdJ-vTdQ&r=567CC38A-FD1B-4DE6-B11B-4166A5669E1B-1&z=https%3A%2F%2Fp03-content.icloud.com%3A443&s=lO5SolOouS9qhYz1oIxKDoGtMpo&hs=ovfPXj3b9XXz9lWKChBmyNq_cug
It looks like the heavy lifting is done by the file referenced there:
https://www.icloud.com/applications/documents/download/en-us/1FCS22.32292/javascript-packed.js
I'd start there looking for the file name etc.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With