Victor Senkevich
Victor Senkevich

Reputation: 11

How to get thumbnails for shared OneDrive files to unauthorized users? This useful OneDrive feature provided in the old API is broken now

My app uses OneDrive API feature to let unauthorized users get thumbnails for shared OneDrive files using old API request:

https:// apis.live.net/v5.0/skydrive/get_item_preview?type=normal&url=[shared_link_to_OneDrive_file]

This feature is broken now (any such links return XMLHttpRequest connection error 0x2eff). And my Windows Store app can not longer provide this feature.

Anyone can try to check it, link to shared OneDrive file:

https://onedrive.live.com/redir?resid=AABF0E8064900F8D!27202&authkey=!AJTeSCuaHMc45eY&v=3&ithint=photo%2cjpg

links to a preview image for shared OneDrive file (according to old OneDrive API "Displaying a preview of a OneDrive item" - https:// msdn.microsoft.com/en-us/library/jj680723.aspx):

https://apis.live.net/v5.0/skydrive/get_item_preview?type=normal&url=https%3A%2F%2Fonedrive.live.com%2Fredir%3Fresid%3DAABF0E8064900F8D!27202%26authkey%3D!AJTeSCuaHMc45eY%26v%3D3%26ithint%3Dphoto%252cjpg generates error: SCRIPT7002: XMLHttpRequest: Network error 0x2eff

Сurrent OneDrive API thumbnail feature:

GET /drive/items/{item-id}/thumbnails/{thumb-id}/{size}

is just for authorized users and can not provide access to thumbnails for shared OneDrive files to unauthorized users

How can a Windows Store app let unauthorized users get thumbnails for shared OneDrive files (videos etc.) using the current OneDrive API? Any ideas?

Upvotes: 1

Views: 1688

Answers (2)

Andrew
Andrew

Reputation: 184

I just figured it out. It is based on the information in this article from Microsoft...

https://learn.microsoft.com/en-ca/onedrive/developer/rest-api/api/driveitem_list_thumbnails?view=odsp-graph-online

... look at the section, "Getting thumbnails while listing DriveItems." It shows you the relevant JSON return structure from a call such as:

GET /me/drive/items/{item-id}/children?$expand=thumbnails

Basically, the JSON return structure gives you string URL's for each of the thumbnail formats. You then create URLSession's to upload these URL's (once you've converted them from String to URL)

Here is an excerpt of code using Swift (Apple):

////////////////////////////////////////////////////////////////////////////////
//
// Download a thumbnail with a URL and label the URLSession with an ID.
//
func downloadThumbnail(url: URL, id: String) {

    // Create a URLSession. This is an object that controls the operation or flow
    // control with respect to asynchronous operations. It sets the callback delegate
    // when the operation is complete.
    let urlSession: URLSession = {
        //let config = URLSessionConfiguration.default
        let config = URLSessionConfiguration.background(withIdentifier: id)
        config.isDiscretionary = true
        config.sessionSendsLaunchEvents = true
        //config.identifier = "file download"
        return URLSession(configuration: config, delegate: self as URLSessionDelegate, delegateQueue: OperationQueue.main)
    }()

    // Create the URLRequest. This is needed so that "Authorization" can be made, as well
    // as the actual HTTP command. The url, on initialization, is the command... along
    // with the "GET" setting of the httpMethod property.
    var request = URLRequest(url: url)

    // Set the Authorization header for the request. We use Bearer tokens, so we specify Bearer + the token we got from the result
    request.setValue("Bearer \(self.accessToken)", forHTTPHeaderField: "Authorization")
    request.httpMethod = "GET"
    request.setValue("application/json", forHTTPHeaderField: "Content-Type")

    // This initiates the asynchronous data task
    let backgroundTask = urlSession.downloadTask(with: request)
    //backgroundTask.earliestBeginDate = Date().addingTimeInterval(60 * 60)
    backgroundTask.countOfBytesClientExpectsToSend = 60
    backgroundTask.countOfBytesClientExpectsToReceive = 15 * 1024
    backgroundTask.resume()

}

... of course you need to have the correct "accessToken," (shown above) but you also have to have written the generic callback function for URLSession, which is:

func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask,
                didFinishDownloadingTo location: URL) {

    Swift.print("DEBUG: urlSession callback reached")

    // This was the identifier that you setup URLSession with
    let id = session.configuration.identifier

    // "location" is the temporary URL that the thumbnail was downloaded to
    let temp = location

    // You can convert this URL into any kind of image object. Just Google it!
}

Cheers, Andreas

Upvotes: 0

Alexandru C.
Alexandru C.

Reputation: 3395

You need to make a call to the following API:

GET /drive/items/{item-id}/thumbnails/{thumb-id}/{size}/content

This call needs to use authorization and returns a redirect to a cache-safe thumbnail location. You can then use this new url to serve thumbnails to unauthenticated users.

e.g.

Request:

GET https://api.onedrive.com/v1.0/drive/items/D094522DE0B10F6D!152/thumbnails/0/small/content
Authorization: bearer <access token>

Response:

HTTP/1.1 302 Found
Location: https://qg3u2w.bn1302.livefilestore.com/y3m1LKnRaQvGEEhv_GU3mVsewg_-aizIXDaVczGwGFIqtNcVSCihLo7s2mNdUrKicuBnB2sGlSwMQTzQw7v34cHLkchKHL_5YC3IMx1SMcpndtdb9bmQ6y2iG4id0HHgCUlgctvYsDrE24XALwXv2KWRUwCCvDJC4hlkqYgnwGBUSQ

You can now use the link in the Location header to access the thumbnail without signing in. This url will change only if the contents of the file change.

You can read more in the documentation here.

Upvotes: 0

Related Questions