Using the OneDrive File Picker in SharePoint Framework Solutions

Lessons Learned from the #SPShire Project

This is the one of my lessons learned from the Shire Hub Intranet project, based on the forthcoming SharePoint Communication Sites.

The lessons in this blog series are:

  1. Previewing and Opening Office Documents from the SharePoint Framework
  2. Using the OneDrive File Picker in SharePoint Framework Solutions
    (this article)
  3. Creating Reusable React Components for SharePoint Framework Solutions

This project on github contains the sample solution for all three articles.

Using the OneDrive File Picker in SharePoint Framework Solutions

NOTE: While this article may still be useful in understanding the series, the code appears to be out of date. At this point I’d recommend using the open source PnP File Picker instead. – BG, April 2020

During the recent webinar explaining the Shire Hub project, MarMikeTollyQuestionk Kashman asked BlueMetal’s Mike Tolly how he developed the needed web parts. According to Tolly, it required “reverse engineering the Microsoft hero web part” to build web parts as rich and advanced as those from Microsoft. This article reveals one of the secrets Mike discovered: how to launch the OneDrive “file picker” to browse SharePoint content, so a user can navigate the libraries and choose a file.

The link picker swings out on an Office UI Fabric Panel component. If you haven’t checked out the Office UI Fabric React Components, you’ve been missing out! Stop right now and browse the catalog, where you can see the components in action and see how incredibly simple they are to use!

The link picker itself runs in an iFrame pointing to /layouts/15/onedrive.aspx with a bunch of query string arguments. Why an iFrame? Well it actually makes a lot of sense, given the amount of complexity in the link picker and the fact that you rarely use it. Why load all that stuff on every page, just on the off chance you need to browse for a document? Over time I’ve developed a love/hate relationship with iFrames, and this is one use I love.

In the sample solution, the code for dealing with the link picker is isolated in a React module called LinkPickerPanel.tsx. Here is the function that builds the URL for the iFrame.


private getDocPickerUrl(){
  const anchor = document.createElement('a');
  anchor.href = this.props.webAbsUrl;

  let typeFilter = '&view=2&p=2&typeFilters=';
  if (this.props.linkType & LinkType.folder) typeFilter += 'folder,';
  if (this.props.linkType & LinkType.doc) typeFilter += '.doc,.docx,.xls,.xlsx,.pot,.potx,.ppt,.pptx,.vsdx,.vsdm,.vsd,';
  if (this.props.linkType & LinkType.image) typeFilter += '.gif,.jpg,.jpeg,.bmp,.dib,.tif,.tiff,.ico,.png,.jxr,';
  if (this.props.linkType & LinkType.page) typeFilter += '.aspx,';
  typeFilter = typeFilter.slice (0,-1); // Trim trailing comma
  typeFilter += '&picker={"sn":false,"v":"files","id":"1","o":"';

 return anchor.href +
   "/_layouts/15/onedrive.aspx?id=" +
   anchor.pathname +
   typeFilter +
   anchor.hostname +
   '","s":"single"}';
}

The LinkPickerPanel has a property that filters the types of documents that can be picked. This is used to build the typeFilters query string parameter; OneDrive takes care of the rest.

The iFrame is rendered on the Panel component and is simple enough in itself.


The link picker iFrame needs a way to communicate with our code when a user selects a document, or cancels out of the link picker. Here are the functions to add and remove the message listener and to handle incoming messages. The component adds the message listener when the panel opens, and removes it when it closes.

private addMessageListener(){
  addEventListener('message',this.onMessageReceived.bind(this), false);
}

private removeMessageListener (){
  removeEventListener('message',this.onMessageReceived.bind(this),false);
}

private onMessageReceived(event){
  if (event.data.indexOf('[OneDrive-FromPicker]',0)===0) {
    const json = JSON.parse(event.data.replace('[OneDrive-FromPicker]',''));
    const eventType = json.type;

    switch (eventType) {
      case 'success':
        const url = json.items[0].sharePoint.url;
        this.resolvePickLink(url);
        this.closeLinkPanel();
        break;
      case 'cancel':
        this.rejectPickLink();
        this.closeLinkPanel();
        break;
    }
  }
}

The messages come in with a heading “[OneDrive-FromPicker]”, followed by a JSON structure that indicates the event type and the link url chosen. There’s probably a lot more you can do with this, but there seems to be no documentation. (If there is documentation I’ve missed please let me know in the comments! I will thank you and update the article. This appears to be similar but not the same.)

The story continues in the next article, where I’ll discuss how this was wrapped into a reusable React component that’s shared by a whole suite of web parts.

6 thoughts on “Using the OneDrive File Picker in SharePoint Framework Solutions

  1. Hello there – this is really useful, many thanks! Do you know if it’s possible to set a flag to enable picking multiple files at once? I can’t figure out a way to do it!

    Like

  2. Hi – I’m back! Hope you are well in our strange new world..!
    Are you still using this method?
    I’m finding today this isn’t working for me any more.
    If you have a site where you’re using this, could you possibly check if yours still works?
    Or if you see a similar error to me in the browser console (looks permissions / authentication related)
    The link picker appears to appear, but the top folder can’t be clicked / navigated into.

    Uncaught (in promise)
    {code: “-2147024894, System.IO.FileNotFoundException”, message: {…}, status: 404, redirectUrl: undefined, authenticate: undefined, …}
    authenticate: undefined
    code: “-2147024894, System.IO.FileNotFoundException”
    correlationId: “26e64b9f-903f-2000-3091-dd47dc95d34e”
    message: {lang: “en-US”, value: “File Not Found.”}
    redirectUrl: undefined
    status: 404

    Like

Leave a comment