Sélecteur de fichiers
Le sélecteur de fichiers v8 vous permet d'utiliser la même fonctionnalité que celle utilisée par le service M365 dans vos solutions. Cela signifie qu'au fur et à mesure que nous itérons et améliorons le service, ces nouvelles capacités apparaissent pour vos utilisateurs !
Ce nouveau « contrôle » est une page hébergée dans le service Microsoft avec laquelle vous interagissez par le biais de messages postaux. La page peut être hébergée soit dans une iframe, soit dans un popup.
Montrez-moi juste l'exemple de code
Vous pouvez trouver la documentation pour le sélecteur 7.2 ici.
Configuration requise
Pour exécuter les échantillons ou utiliser le contrôle dans votre solution, vous devrez créer une application AAD. Vous pouvez suivre les étapes suivantes :
- Créez un nouvel enregistrement d'application AAD, notez l'ID de l'application.
- Sous authentification, créez un nouveau registre d'application monopage
- Définir l'uri de redirection
https://localhost
(ceci est pour tester les échantillons) - Assurez-vous que les jetons d'accès et les jetons d'identification sont vérifiés.
- Vous pouvez éventuellement configurer cette application pour le multitenant, mais cela sort du cadre de cet article.
- Définir l'uri de redirection
- Sous Autorisations API
- Ajouter
Files.Read.All
,Sites.Read.All
, LaisserUser.Read
pour les permissions déléguées du graphique - Ajouter
AllSites.Read
,MyFiles.Read
pour les permissions déléguées de SharePoint
- Ajouter
Si vous développez dans SharePoint Framework, vous pouvez demander ces autorisations dans le manifeste de l'application avec la ressource « SharePoint » et « Microsoft Graph ».
Pour permettre à l’utilisateur de charger des fichiers et de créer des dossiers dans l’expérience du sélecteur, vous pouvez demander l’accès à
Files.ReadWrite.All
,Sites.ReadWrite.All
,AllSites.Write
etMyFiles.Write
.
Autorisations
Le sélecteur de fichiers fonctionne toujours à l’aide d’autorisations déléguées et, par conséquent, peut uniquement accéder aux fichiers et dossiers auxquels l’utilisateur actuel a déjà accès.
Au minimum, vous devez demander à SharePoint MyFiles.l’autorisation Lecture de lire des fichiers à partir des sites OneDrive et SharePoint d’un utilisateur.
Consultez le tableau ci-dessous pour comprendre quelle autorisation est requise en fonction des opérations que vous souhaitez effectuer. Toutes les autorisations de ce tableau font référence aux autorisations déléguées.
Lecture | Write | |
---|---|---|
OneDrive | SharePoint.MyFiles.Read ou Graph.Files.Read |
SharePoint.MyFiles.Write ou Graph.Files.ReadWrite |
SharePoint Sites | SharePoint.MyFiles.Read ou Graph.Files.Read ou SharePoint.AllSites.Read |
SharePoint.MyFiles.Write ou Graph.Files.ReadWrite ou SharePoint.AllSites.Write |
Canaux Teams | Graph.ChannelSettings.Read.All et SharePoint.AllSites.Read | Graph.ChannelSettings.Read.All et SharePoint.AllSites.Write |
Mode de fonctionnement
Pour utiliser le contrôle, vous devez :
- Faites une demande POST à la page « control » hébergée à /_layouts/15/FilePicker.aspx. Cette demande permet de fournir certains paramètres, le principal étant la configuration du sélecteur.
- Configurez la messagerie entre votre application hôte et le contrôle en utilisant postMessage et les ports de message.
- Une fois le canal de communication établi, vous devez répondre à diverses « commandes », dont la première consiste à fournir des jetons d'authentification.
- Enfin, vous devrez répondre à des messages de commande supplémentaires pour fournir des jetons d'authentification nouveaux ou différents, traiter les fichiers prélevés ou fermer la fenêtre contextuelle.
Les sections suivantes expliquent chaque étape.
Nous disposons également d'une série d'échantillons montrant différentes manières d'intégrer le contrôle.
Lancer le sélecteur
Pour lancer le sélecteur, vous devez créer une « fenêtre » qui peut être une iframe ou une popup. Une fois que vous avez une fenêtre, vous devez construire un formulaire et POST le formulaire à l'URL{baseUrl}/_layouts/15/FilePicker.aspx
avec les paramètres de la chaîne de requête définis.
La {baseUrl}
valeur ci-dessus est soit l 'url SharePoint du site web cible, soit l' onedrive de l'utilisateur. Voici quelques exemples : «https://tenant.sharepoint.com/sites/dev" ; ou "https://tenant-my.sharepoint.com" ;.
Configuration du consommateur OneDrive
nom | Descriptions |
---|---|
autorité | https://login.microsoftonline.com/consumers |
Portée | OneDrive.ReadWrite ou OneDrive.ReadOnly |
baseUrl | https://onedrive.live.com/picker |
Lorsque vous demandez un jeton, vous utilisez ou
OneDrive.ReadOnly
OneDrive.ReadWrite
lorsque vous demandez le jeton. Lorsque vous demandez les autorisations pour votre application, vous sélectionnez pourFiles.Read
ouFiles.ReadWrite
(ou une autre étendue Files.X).
// create a new window. The Picker's recommended maximum size is 1080x680, but it can scale down to
// a minimum size of 250x230 for very small screens or very large zoom.
const win = window.open("", "Picker", "width=1080,height=680");
// we need to get an authentication token to use in the form below (more information in auth section)
const authToken = await getToken({
resource: baseUrl,
command: "authenticate",
type: "SharePoint",
});
// to use an iframe you can use code like:
// const frame = document.getElementById("iframe-id");
// const win = frame.contentWindow;
// now we need to construct our query string
// options: These are the picker configuration, see the schema link for a full explaination of the available options
const queryString = new URLSearchParams({
filePicker: JSON.stringify(options),
locale: 'en-us'
});
// Use MSAL to get a token for your app, specifying the resource as {baseUrl}.
const accessToken = await getToken(baseUrl);
// we create the absolute url by combining the base url, appending the _layouts path, and including the query string
const url = baseUrl + `/_layouts/15/FilePicker.aspx?${queryString}`);
// create a form
const form = win.document.createElement("form");
// set the action of the form to the url defined above
// This will include the query string options for the picker.
form.setAttribute("action", url);
// must be a post request
form.setAttribute("method", "POST");
// Create a hidden input element to send the OAuth token to the Picker.
// This optional when using a popup window but required when using an iframe.
const tokenInput = win.document.createElement("input");
tokenInput.setAttribute("type", "hidden");
tokenInput.setAttribute("name", "access_token");
tokenInput.setAttribute("value", accessToken);
form.appendChild(tokenInput);
// append the form to the body
win.document.body.append(form);
// submit the form, this will load the picker page
form.submit();
Configuration du sélecteur
Le sélecteur est configuré en sérialisant un objet json contenant les paramètres souhaités, et en l'ajoutant aux valeurs de la chaîne de requête comme indiqué dans la section Initier le sélecteur. Vous pouvez également afficher le schéma complet. Vous devez au moins fournir les paramètres d'authentification, d'entrée et de messagerie.
Un exemple d'objet de paramètres minimaux est présenté ci-dessous. Cela configure la messagerie sur le canal 27, fait savoir au sélecteur que nous pouvons fournir des jetons, et que nous voulons que l'onglet « Mes fichiers » représente les fichiers OneDrive de l’utilisateur. Cette configuration utiliserait un baseUrl de la forme « https://{tenant}-my.sharepoint.com » ;
const channelId = uuid(); // Always use a unique id for the channel when hosting the picker.
const options = {
sdk: "8.0",
entry: {
oneDrive: {}
},
// Applications must pass this empty `authentication` option in order to obtain details item data
// from the picker, or when embedding the picker in an iframe.
authentication: {},
messaging: {
origin: "http://localhost:3000",
channelId: channelId
},
}
Le sélecteur est conçu pour fonctionner avec OneDrive OU SharePoint dans une instance donnée et une seule des sections de saisie doit être incluse.
Localisation
L’interface du sélecteur de fichiers prend en charge la localisation pour le même ensemble de langues que SharePoint.
Pour définir la langue du sélecteur de fichiers, utilisez le paramètre de chaîne de requête locale
, défini sur l’une des valeurs LCID de la liste ci-dessus.
Établir un message
Une fois la fenêtre créée et le formulaire soumis, vous devrez établir un canal de messagerie. Il est utilisé pour recevoir les commandes du sélecteur et y répondre.
let port: MessagePort;
function initializeMessageListener(event: MessageEvent): void {
// we validate the message is for us, win here is the same variable as above
if (event.source && event.source === win) {
const message = event.data;
// the channelId is part of the configuration options, but we could have multiple pickers so that is supported via channels
// On initial load and if it ever refreshes in its window, the Picker will send an 'initialize' message.
// Communication with the picker should subsequently take place using a `MessageChannel`.
if (message.type === "initialize" && message.channelId === options.messaging.channelId) {
// grab the port from the event
port = event.ports[0];
// add an event listener to the port (example implementation is in the next section)
port.addEventListener("message", channelMessageListener);
// start ("open") the port
port.start();
// tell the picker to activate
port.postMessage({
type: "activate",
});
}
}
};
// this adds a listener to the current (host) window, which the popup or embed will message when ready
window.addEventListener("message", messageEvent);
Mise en œuvre du récepteur de messages
Votre solution doit traiter divers messages provenant du sélecteur, classés comme des notifications ou des commandes. Les notifications n'attendent aucune réponse et peuvent être considérées comme des informations de journal. La seule exception est la page-loaded
notification mise en évidence ci-dessous, qui vous indique que le sélecteur est prêt.
Les commandes exigent que vous accusiez réception et, selon la commande, que vous répondiez. Cette section montre un exemple d'implémentation de la channelMessageListener
fonction ajoutée comme un écouteur d'événement au port. Les sections suivantes traitent en détail des notifications et des commandes.
async function channelMessageListener(message: MessageEvent): Promise<void> {
const payload = message.data;
switch (payload.type) {
case "notification":
const notification = payload.data;
if (notification.notification === "page-loaded") {
// here we know that the picker page is loaded and ready for user interaction
}
console.log(message.data);
break;
case "command":
// all commands must be acknowledged
port.postMessage({
type: "acknowledge",
id: message.data.id,
});
// this is the actual command specific data from the message
const command = payload.data;
// command.command is the string name of the command
switch (command.command) {
case "authenticate":
// the first command to handle is authenticate. This command will be issued any time the picker requires a token
// 'getToken' represents a method that can take a command and return a valid auth token for the requested resource
try {
const token = await getToken(command);
if (!token) {
throw new Error("Unable to obtain a token.");
}
// we report a result for the authentication via the previously established port
port.postMessage({
type: "result",
id: message.data.id,
data: {
result: "token",
token: token,
}
});
} catch (error) {
port.postMessage({
type: "result",
id: message.data.id,
data: {
result: "error",
error: {
code: "unableToObtainToken",
message: error.message
}
}
});
}
break;
case "close":
// in the base of popup this is triggered by a user request to close the window
await close(command);
break;
case "pick":
try {
await pick(command);
// let the picker know that the pick command was handled (required)
port.postMessage({
type: "result",
id: message.data.id,
data: {
result: "success"
}
});
} catch (error) {
port.postMessage({
type: "result",
id: message.data.id,
data: {
result: "error",
error: {
code: "unusableItem",
message: error.message
}
}
});
}
break;
default:
// Always send a reply, if if that reply is that the command is not supported.
port.postMessage({
type: "result",
id: message.data.id,
data: {
result: "error",
error: {
code: "unsupportedCommand",
message: command.command
}
}
});
break;
}
break;
}
}
Obtenir un jeton
Le contrôle nécessite que nous puissions lui fournir des jetons d’authentification basés sur la commande envoyée. Pour ce faire, nous créons une méthode qui prend une commande et retourne un jeton comme indiqué ci-dessous. Nous utilisons le @azure/msal-browser
package pour gérer le travail d’authentification.
Actuellement, le contrôle s’appuie sur des jetons SharePoint et non sur Graph. Vous devez donc vous assurer que votre ressource est correcte et que vous ne pouvez pas réutiliser les jetons pour les appels Graph.
import { PublicClientApplication, Configuration, SilentRequest } from "@azure/msal-browser";
import { combine } from "@pnp/core";
import { IAuthenticateCommand } from "./types";
const app = new PublicClientApplication(msalParams);
async function getToken(command: IAuthenticateCommand): Promise<string> {
let accessToken = "";
const authParams = { scopes: [`${combine(command.resource, ".default")}`] };
try {
// see if we have already the idtoken saved
const resp = await app.acquireTokenSilent(authParams!);
accessToken = resp.accessToken;
} catch (e) {
// per examples we fall back to popup
const resp = await app.loginPopup(authParams!);
app.setActiveAccount(resp.account);
if (resp.idToken) {
const resp2 = await app.acquireTokenSilent(authParams!);
accessToken = resp2.accessToken;
} else {
// throw the error that brought us here
throw e;
}
}
return accessToken;
}
Résultats de l’élément sélectionné
Lorsqu’un élément est sélectionné, le sélecteur retourne, via le canal de messagerie, un tableau d’éléments sélectionnés. Bien qu’il existe un ensemble d’informations pouvant être retournées, les éléments suivants sont toujours inclus :
{
"id": string,
"parentReference": {
"driveId": string
},
"@sharePoint.endpoint": string
}
À l’aide de cela, vous pouvez construire une URL pour effectuer une requête GET afin d’obtenir toutes les informations dont vous avez besoin sur le fichier sélectionné. Elle se présente généralement sous la forme suivante :
@sharePoint.endpoint + /drives/ + parentReference.driveId + /items/ + id
Vous devez inclure un jeton valide avec les droits appropriés pour lire le fichier dans la demande.
Chargement de fichiers
Si vous accordez Files.ReadWrite.All
des autorisations à l’application que vous utilisez pour les jetons de sélecteur, un widget dans le menu supérieur s’affiche, ce qui vous permet de charger des fichiers et des dossiers dans la bibliothèque de documents OneDrive ou SharePoint. Aucune autre modification de configuration n’est requise, ce comportement est contrôlé par les autorisations d’application + utilisateur. Notez que si l’utilisateur n’a pas accès à l’emplacement de chargement, le sélecteur n’affiche pas l’option .
Conseils de personnalisation
Les applications qui s’intègrent au sélecteur de fichiers Microsoft OneDrive peuvent également choisir de promouvoir leur intégration à OneDrive auprès des clients. Étant donné que OneDrive propose à la fois une offre grand public et commerciale, les options suivantes sont disponibles pour être affichées dans les interfaces d’application tierces :
- Microsoft OneDrive (personnel)
- Peut également être affiché en tant que Microsoft OneDrive pour personnel
- Microsoft OneDrive (professionnel/scolaire)
- Peut également être affiché en tant que Microsoft OneDrive pour les professionnels ou les établissements scolaires