Erstellen, Aktualisieren und Löschen von Dateien in einem Container

Abgeschlossen

In dieser Übung aktualisieren Sie das vorhandene Projekt, um Dateien in einem SharePoint Embedded-Container zu speichern.

Hinzufügen von Microsoft Graph-Typdeklarationen zum Projekt

Bevor wir die neuen React-Komponenten erstellen, beginnen wir mit dem Aktualisieren des Projekts.

In dieser Übung verwenden wir typen, die von Microsoft Graph bereitgestellt werden. Da wir das npm-Paket, das sie enthält, nicht installiert haben, müssen wir dies zuerst tun.

Führen Sie in der Befehlszeile den folgenden Befehl im Stammordner für unser Projekt aus:

npm install @microsoft/microsoft-graph-types -DE

Aktualisieren der React Containers-Komponente zum Anzeigen von Dateien

Erinnern Sie sich an die vorherige Übung, dass wir einen Platzhalter in unserer Containerkomponente gelassen haben, der verwendet wird, um den Inhalt des ausgewählten Containers anzuzeigen.

Wir haben unsere Files Komponente nicht erstellt, aber beginnen wir damit, die Containers Komponente zu aktualisieren, um den Platzhalter durch die Komponente zu ersetzen, die Files wir erstellen.

Suchen Und öffnen Sie die Datei ./src/components/containers.tsx .

Fügen Sie die folgende Import-Anweisung zur Liste der vorhandenen Importe am Anfang der Datei hinzu:

import { Files } from "./files";

Suchen Sie als Nächstes den folgenden Platzhaltercode am Ende der Datei...

{selectedContainer && (`[[TOOD]] container "${selectedContainer.displayName}" contents go here`)}

… und ersetzen Sie sie durch den folgenden Code:

{selectedContainer && (<Files container={selectedContainer} />)}

Erstellen der React-Komponente "Dateien"

Beginnen wir damit, eine neue React-Komponente zu erstellen, um den Inhalt der Container anzuzeigen und zu verwalten.

Erstellen Sie die neue Datei ./src/components/files.tsx, und fügen Sie den folgenden Code hinzu. Dies ist die Bausteinekomponente, die alle Importe und das Gerüst unseres Bauteils umfasst:

import React, {
  useState,
  useEffect,
  useRef
} from 'react';
import { Providers } from "@microsoft/mgt-element";
import {
  AddRegular, ArrowUploadRegular,
  FolderRegular, DocumentRegular,
  SaveRegular, DeleteRegular,
} from '@fluentui/react-icons';
import {
  Button, Link, Label, Spinner,
  Input, InputProps, InputOnChangeData,
  Dialog, DialogActions, DialogContent, DialogBody, DialogSurface, DialogTitle, DialogTrigger,
  DataGrid, DataGridProps,
  DataGridHeader, DataGridHeaderCell,
  DataGridBody, DataGridRow,
  DataGridCell,
  TableColumnDefinition, createTableColumn,
  TableRowId,
  TableCellLayout,
  OnSelectionChangeData,
  SelectionItemId,
  Toolbar, ToolbarButton,
  makeStyles
} from "@fluentui/react-components";
import {
  DriveItem
} from "@microsoft/microsoft-graph-types-beta";
import { IContainer } from "./../common/IContainer";
require('isomorphic-fetch');

interface IFilesProps {
  container: IContainer;
}

interface IDriveItemExtended extends DriveItem {
  isFolder: boolean;
  modifiedByName: string;
  iconElement: JSX.Element;
  downloadUrl: string;
}

export const Files = (props: IFilesProps) => {

  // BOOKMARK 1 - constants & hooks

  // BOOKMARK 2 - handlers go here

  // BOOKMARK 3 - component rendering return (
  return
  (
    <div>
    </div>
  );
}

export default Files;

Hinweis

Beachten Sie die // BOOKMARK # Kommentare in der Komponente. Diese stellen sicher, dass Sie Code an den richtigen Stellen hinzufügen.

Anzeigen einer Liste der ausgewählten Containerinhalte

Zunächst müssen wir den Inhalt des ausgewählten Containers anzeigen. Dazu verwenden wir die DataGrid Komponente aus der React-Bibliothek der Fluent-Benutzeroberfläche.

Fügen Sie das folgende Markup innerhalb des <div> -Elements in der return() -Anweisung nach dem // BOOKMARK 3 Kommentar hinzu:

<DataGrid
  items={driveItems}
  columns={columns}
  getRowId={(item) => item.id}
  resizableColumns
  columnSizingOptions={columnSizingOptions}
  >
  <DataGridHeader>
    <DataGridRow>
      {({ renderHeaderCell }) => (
        <DataGridHeaderCell>{renderHeaderCell()}</DataGridHeaderCell>
      )}
    </DataGridRow>
  </DataGridHeader>
  <DataGridBody<IDriveItemExtended>>
    {({ item, rowId }) => (
      <DataGridRow<IDriveItemExtended> key={rowId}>
        {({ renderCell, columnId }) => (
          <DataGridCell>
            {renderCell(item)}
          </DataGridCell>
        )}
      </DataGridRow>
    )}
  </DataGridBody>
</DataGrid>

Enthält DataGrid einige Verweise auf Auflistungen, Einstellungen und Methoden, die wir einrichten müssen. Beginnen wir mit den visuellen Elementen, und dann erhalten wir die Daten.

Die Größe der DataGrid Spalten im kann entsprechend den von uns festgelegten Eigenschaften geändert werden. Erstellen Sie eine neue Konstante, columnSizingOptions, und fügen Sie den Code unmittelbar vor dem // BOOKMARK 3 Kommentar hinzu:

const columnSizingOptions = {
  driveItemName: {
    minWidth: 150,
    defaultWidth: 250,
    idealWidth: 200
  },
  lastModifiedTimestamp: {
    minWidth: 150,
    defaultWidth: 150
  },
  lastModifiedBy: {
    minWidth: 150,
    defaultWidth: 150
  },
  actions: {
    minWidth: 250,
    defaultWidth: 250
  }
};

Definieren Sie als Nächstes die Struktur- und Renderingeinstellungen für alle Spalten in DataGrid. Erstellen Sie dazu eine neue Sammlung , columnsund fügen Sie sie unmittelbar vor der erstellung hinzu columnSizingOptions :

const columns: TableColumnDefinition<IDriveItemExtended>[] = [
  createTableColumn({
    columnId: 'driveItemName',
    renderHeaderCell: () => {
      return 'Name'
    },
    renderCell: (driveItem) => {
      return (
        <TableCellLayout media={driveItem.iconElement}>
          <Link href={driveItem!.webUrl!} target='_blank'>{driveItem.name}</Link>
        </TableCellLayout>
      )
    }
  }),
  createTableColumn({
    columnId: 'lastModifiedTimestamp',
    renderHeaderCell: () => {
      return 'Last Modified'
    },
    renderCell: (driveItem) => {
      return (
        <TableCellLayout>
          {driveItem.lastModifiedDateTime}
        </TableCellLayout>
      )
    }
  }),
  createTableColumn({
    columnId: 'lastModifiedBy',
    renderHeaderCell: () => {
      return 'Last Modified By'
    },
    renderCell: (driveItem) => {
      return (
        <TableCellLayout>
          {driveItem.modifiedByName}
        </TableCellLayout>
      )
    }
  }),
  createTableColumn({
    columnId: 'actions',
    renderHeaderCell: () => {
      return 'Actions'
    },
    renderCell: (driveItem) => {
      return (
        <>
          <Button aria-label="Download"
            disabled={!selectedRows.has(driveItem.id as string)}
            icon={<SaveRegular />}>Download</Button>
          <Button aria-label="Delete"
            icon={<DeleteRegular />}>Delete</Button>
        </>
      )
    }
  }),
];

Dieser Code verwendet die Hilfsmethode createTableColumn() , um jeder Spalte eine ID zu geben und anzugeben, wie die Header- und Textzellen in der Tabelle gerendert werden.

Fügen Sie bei der DataGrid Konfiguration die folgenden Konstanten hinzu, um den Zustand der React-App mit den Eigenschaften zu verwalten, die unser vorhandener Code verwendet. Fügen Sie den folgenden Code unmittelbar vor dem // BOOKMARK 1-Kommentar ein:

const [driveItems, setDriveItems] = useState<IDriveItemExtended[]>([]);
const [selectedRows, setSelectedRows] = useState<Set<SelectionItemId>>(new Set<TableRowId>([1]));

Nun fügen wir einige Handler hinzu, um die Daten aus unserem Container abzurufen und anzuzeigen.

Fügen Sie den folgenden Handler und React-Hook hinzu, um den Inhalt des ausgewählten Containers abzurufen. Der useEffect Hook wird ausgeführt, wenn die Komponente zum ersten Mal gerendert wird, sowie wenn sich die Eingabeeigenschaften der <Files />Komponente ändern.

Fügen Sie den folgenden Code unmittelbar vor dem // BOOKMARK 2-Kommentar ein:

useEffect(() => {
  (async () => {
    loadItems();
  })();
}, [props]);

const loadItems = async (itemId?: string) => {
  try {
    const graphClient = Providers.globalProvider.graph.client;
    const driveId = props.container.id;
    const driveItemId = itemId || 'root';

    // get Container items at current level
    const graphResponse = await graphClient.api(`/drives/${driveId}/items/${driveItemId}/children`).get();
    const containerItems: DriveItem[] = graphResponse.value as DriveItem[]
    const items: IDriveItemExtended[] = [];
    containerItems.forEach((driveItem: DriveItem) => {
      items.push({
        ...driveItem,
        isFolder: (driveItem.folder) ? true : false,
        modifiedByName: (driveItem.lastModifiedBy?.user?.displayName) ? driveItem.lastModifiedBy!.user!.displayName : 'unknown',
        iconElement: (driveItem.folder) ? <FolderRegular /> : <DocumentRegular />,
        downloadUrl: (driveItem as any)['@microsoft.graph.downloadUrl']
      });
    });
    setDriveItems(items);
  } catch (error: any) {
    console.error(`Failed to load items: ${error.message}`);
  }
};

Die loadItems Funktion verwendet den Microsoft Graph-Client, um eine Liste aller Dateien innerhalb des aktuellen Ordners abzurufen, wobei standardmäßig der root verwendet wird, wenn kein Ordner bereits ausgewählt ist.

Anschließend wird die von Microsoft Graph zurückgegebene Auflistung von DriveItems verwendet und einige weitere Eigenschaften hinzugefügt, um den Code später zu vereinfachen. Am Ende der -Methode wird die setDriveitems() Zustandsaccessormethode aufgerufen, die ein erneutes Rendern der Komponente auslöst. Die driveItems werden für die DataGrid.items -Eigenschaft festgelegt, die erklärt, warum die Tabelle einige Informationen anzeigt.

Testen des Renderns des Auflistens des Inhalts eines Containers

Testen Sie nun die clientseitige React-App, um sicherzustellen, dass die <Files /> Komponente den Inhalt des ausgewählten Containers anzeigt.

Führen Sie über die Befehlszeile im Stammordner des Projekts den folgenden Befehl aus:

npm run start

Wenn der Browser geladen wird, melden Sie sich mit demselben Geschäfts-, Schul- und Unikonto an, das Sie verwendet haben.

Wählen Sie nach der Anmeldung einen vorhandenen Container aus. Wenn dieser Container bereits Inhalte enthält, wird er wie folgt angezeigt:

Screenshot: Grundlegendes DataGrid mit dem Inhalt unseres Containers.

Wenn Sie die Datei auswählen, in diesem Fall ein Word-Dokument, wird eine neue Registerkarte geöffnet, und die URL des Elements wird geladen. In diesem Beispiel wird die Datei in Word Online geöffnet.

Unterstützung für das Herunterladen von Dateien hinzufügen

Nachdem die Inhaltsanzeigefunktion abgeschlossen ist, aktualisieren wir die Komponente, um das Herunterladen von Dateien zu unterstützen.

Fügen Sie zunächst den folgenden Code unmittelbar vor dem // BOOKMARK 1 Kommentar hinzu:

const downloadLinkRef = useRef<HTMLAnchorElement>(null);

Als Nächstes möchten wir sicherstellen, dass ein Element in ausgewählt DataGrid ist, bevor es heruntergeladen werden kann. Andernfalls wird die Schaltfläche Herunterladen so deaktiviert, wie sie derzeit ist.

DataGridFügen Sie in drei Eigenschaften hinzu, um festzulegen, dass es einen Auswahlmodus für ein einzelnes Element unterstützt (selectionMode), und verfolgen Sie, welche Elemente ausgewählt werden (selectedItems) und was zu tun ist, wenn sich die Auswahl ändert (onSelectionChange).

<DataGrid
  ...
  selectionMode='single'
  selectedItems={selectedRows}
  onSelectionChange={onSelectionChange}>

Fügen Sie als Nächstes den folgenden Handler unmittelbar vor dem // BOOKMARK 2 Kommentar hinzu:

const onSelectionChange: DataGridProps["onSelectionChange"] = (event: React.MouseEvent | React.KeyboardEvent, data: OnSelectionChangeData): void => {
  setSelectedRows(data.selectedItems);
}

Wenn nun ein Element in der Liste ausgewählt ist, sehen Sie, dass die Schaltfläche Herunterladen nicht mehr deaktiviert ist.

Screenshot der aktivierten Schaltfläche

Die Downloadoption verwendet einen ausgeblendeten Link, mit dem wir zuerst den Downloadlink für das ausgewählte Element programmgesteuert festlegen und dann programmgesteuert die folgenden Aktionen ausführen:

  1. Legen Sie die URL des Links auf die Download-URL des Elements fest.
  2. Wählen Sie den Link aus.

Dadurch wird der Download für den Benutzer ausgelöst.

Fügen Sie das folgende Markup direkt nach dem Öffnen <div> in der return() -Methode hinzu:

<a ref={downloadLinkRef} href="" target="_blank" style={{ display: 'none' }} />

Suchen Sie nun die vorhandene columns Konstante, die Sie zuvor hinzugefügt haben, und suchen Sie die , die createTableColumn auf verweist columnId: 'actions'. Fügen Sie in der renderCell -Eigenschaft einen onClick Handler hinzu, der aufruft onDownloadItemClick. Die Schaltfläche sollte wie folgt aussehen, wenn Sie fertig sind:

<Button aria-label="Download"
        disabled={!selectedRows.has(driveItem.id as string)}
        icon={<SaveRegular />}
        onClick={() => onDownloadItemClick(driveItem.downloadUrl)}>Download</Button>

Fügen Sie schließlich den folgenden Handler unmittelbar nach dem vorhandenen onSelectionChange Ereignishandler hinzu, den Sie zuvor hinzugefügt haben. Dadurch werden die beiden zuvor erwähnten programmgesteuerten Schritte behandelt:

const onDownloadItemClick = (downloadUrl: string) => {
  const link = downloadLinkRef.current;
  link!.href = downloadUrl;
  link!.click();
}

Speichern Sie Ihre Änderungen, aktualisieren Sie den Browser, und wählen Sie den Link Herunterladen aus, um zu sehen, wie die Datei heruntergeladen wird.

Screenshot der neuen Unterstützung für das Herunterladen der Datei.

Hinzufügen der Möglichkeit zum Erstellen eines Ordners in einem Container

Wir setzen den Aufbau der <Files /> Komponente fort, indem wir Unterstützung für das Erstellen und Anzeigen von Ordnern hinzufügen.

Fügen Sie zunächst den folgenden Code unmittelbar vor dem // BOOKMARK 1 Kommentar hinzu. Dadurch werden die erforderlichen React-Zustandswerte hinzugefügt, die wir verwenden:

const [folderId, setFolderId] = useState<string>('root');
const [folderName, setFolderName] = useState<string>('');
const [creatingFolder, setCreatingFolder] = useState<boolean>(false);
const [newFolderDialogOpen, setNewFolderDialogOpen] = useState(false);

Um einen neuen Ordner zu erstellen, wird dem Benutzer ein Dialogfeld angezeigt, wenn er eine Schaltfläche in der Symbolleiste auswählt.

Fügen Sie in der return() -Methode unmittelbar vor den <DataGrid>folgenden Code hinzu, um den Dialog zu implementieren:

<Toolbar>
  <ToolbarButton vertical icon={<AddRegular />} onClick={() => setNewFolderDialogOpen(true)}>New Folder</ToolbarButton>
</Toolbar>

<Dialog open={newFolderDialogOpen}>
  <DialogSurface>
    <DialogBody>
      <DialogTitle>Create New Folder</DialogTitle>
      <DialogContent className={styles.dialogContent}>
        <Label htmlFor={folderName}>Folder name:</Label>
        <Input id={folderName} className={styles.dialogInputControl} autoFocus required
          value={folderName} onChange={onHandleFolderNameChange}></Input>
        {creatingFolder &&
          <Spinner size='medium' label='Creating folder...' labelPosition='after' />
        }
      </DialogContent>
      <DialogActions>
        <DialogTrigger disableButtonEnhancement>
          <Button appearance="secondary" onClick={() => setNewFolderDialogOpen(false)} disabled={creatingFolder}>Cancel</Button>
        </DialogTrigger>
        <Button appearance="primary"
          onClick={onFolderCreateClick}
          disabled={creatingFolder || (folderName === '')}>Create Folder</Button>
      </DialogActions>
    </DialogBody>
  </DialogSurface>
</Dialog>

Das Dialogfeld verwendet einige benutzerdefinierte Stile, die wir noch nicht hinzugefügt haben. Fügen Sie zunächst den folgenden Code unmittelbar vor der Deklaration der Files Komponente hinzu:

const useStyles = makeStyles({
  dialogInputControl: {
    width: '400px',
  },
  dialogContent: {
    display: 'flex',
    flexDirection: 'column',
    rowGap: '10px',
    marginBottom: '25px'
  }
});

Fügen Sie dann den folgenden Code unmittelbar vor der return() -Methode in unserer -Komponente hinzu:

const styles = useStyles();

Nachdem die Benutzeroberfläche eingerichtet wurde, müssen wir nun einige Handler hinzufügen. Fügen Sie die folgenden Handler unmittelbar vor dem // BOOKMARK 2 Kommentar hinzu. Diese behandeln das Öffnen des Dialogfelds, speichern den Wert des Neuen Ordnernamens und was geschieht, wenn sie die Schaltfläche im Dialogfeld auswählen:

const onFolderCreateClick = async () => {
  setCreatingFolder(true);

  const currentFolderId = folderId;
  const graphClient = Providers.globalProvider.graph.client;
  const endpoint = `/drives/${props.container.id}/items/${currentFolderId}/children`;
  const data = {
    "name": folderName,
    "folder": {},
    "@microsoft.graph.conflictBehavior": "rename"
  };
  await graphClient.api(endpoint).post(data);

  await loadItems(currentFolderId);

  setCreatingFolder(false);
  setNewFolderDialogOpen(false);
};

const onHandleFolderNameChange: InputProps["onChange"] = (event: React.ChangeEvent<HTMLInputElement>, data: InputOnChangeData): void => {
  setFolderName(data?.value);
};

Speichern Sie Ihre Änderungen, aktualisieren Sie den Browser, und wählen Sie über dem Inhalt des Containers die Schaltfläche Neuer Ordner aus:

Screenshot: Schaltfläche

Wählen Sie die Schaltfläche Neuer Ordner aus, geben Sie einen Namen ein, und wählen Sie im Dialogfeld die Schaltfläche Ordner erstellen aus.

Screenshot des Dialogfelds

Wenn der Ordner erstellt wird, wird er in der Inhaltstabelle aufgeführt:

Screenshot des neuen Ordners im Container.

Wir müssen eine weitere Änderung an unserer Komponente vornehmen. Wenn Sie jetzt einen Ordner auswählen, wird die URL auf einer neuen Registerkarte gestartet, ohne dass die App ausgelassen wird. Das ist nicht das, was wir wollen... Soll ein Drilldown in den Ordner ausgeführt werden.

Lassen Sie uns dies beheben, indem Sie die vorhandene columns Konstante suchen, die Sie zuvor hinzugefügt haben, und die suchen, die createTableColumn auf verweist columnId: 'driveItemName'. Ersetzen Sie in der renderCell -Eigenschaft die vorhandene <Link /> Komponente durch den folgenden Code. Dadurch werden zwei Verknüpfungen generiert, die darauf basieren, ob das aktuelle Element, das gerendert wird, ein Ordner oder eine Datei ist:

{(!driveItem.isFolder)
  ? <Link href={driveItem!.webUrl!} target='_blank'>{driveItem.name}</Link>
  : <Link onClick={() => {
    loadItems(driveItem.id);
    setFolderId(driveItem.id as string)
  }}>{driveItem.name}</Link>
}

Wenn Sie nun einen Ordner auswählen, zeigt die App den Inhalt des Ordners an.

Hinzufügen der Möglichkeit zum Löschen einer Datei oder eines Ordners

Der nächste Schritt besteht darin, die Möglichkeit zum Löschen eines Ordners oder einer Datei aus dem Container hinzuzufügen.

Um dies zu tun, fügen Sie zunächst den folgenden Code zur liste der useState() vorhandenen Aufrufe vor dem // BOOKMARK 1 Kommentar hinzu.

const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);

Fügen Sie als Nächstes ein Dialogfeld hinzu, das als Bestätigung fungiert, wenn der Benutzer die Schaltfläche Löschen auswählt. Fügen Sie den folgenden Code direkt nach der vorhandenen <Dialog> Komponente in der return() -Methode hinzu:

<Dialog open={deleteDialogOpen} modalType='modal' onOpenChange={() => setSelectedRows(new Set<TableRowId>([0]))}>
  <DialogSurface>
    <DialogBody>
      <DialogTitle>Delete Item</DialogTitle>
      <DialogContent>
        <p>Are you sure you want to delete this item?</p>
      </DialogContent>
      <DialogActions>
        <DialogTrigger>
          <Button
            appearance='secondary'
            onClick={() => setDeleteDialogOpen(false)}>Cancel</Button>
        </DialogTrigger>
        <Button
          appearance='primary'
          onClick={onDeleteItemClick}>Delete</Button>
      </DialogActions>
    </DialogBody>
  </DialogSurface>
</Dialog>

Aktualisieren Sie die Schaltfläche Löschen , um etwas zu tun, wenn sie ausgewählt ist. Suchen Sie die vorhandene columns Konstante, die Sie zuvor hinzugefügt haben, und suchen Sie die , die createTableColumn auf verweist columnId: 'actions'. Fügen Sie in der renderCell -Eigenschaft einen onClick Handler hinzu, der aufruft onDeleteDialogOpen. Die Schaltfläche sollte wie folgt aussehen, wenn Sie fertig sind:

<Button aria-label="Delete"
        icon={<DeleteRegular />}
        onClick={() => setDeleteDialogOpen(true)}>Delete</Button>

Fügen Sie schließlich den folgenden Code unmittelbar vor dem // BOOKMARK 2 Kommentar hinzu, um das Löschen des aktuell ausgewählten Elements zu behandeln:

const onDeleteItemClick = async () => {
  const graphClient = Providers.globalProvider.graph.client;
  const endpoint = `/drives/${props.container.id}/items/${selectedRows.entries().next().value[0]}`;
  await graphClient.api(endpoint).delete();
  await loadItems(folderId || 'root');
  setDeleteDialogOpen(false);
}

Speichern Sie Ihre Änderungen, und aktualisieren Sie den Browser. Wählen Sie die Schaltfläche Löschen für einen der vorhandenen Ordner oder Dateien in Ihrer Sammlung aus. Das Bestätigungsdialogfeld wird angezeigt, und wenn Sie die Schaltfläche Löschen im Dialogfeld auswählen, wird die Inhaltstabelle des Containers aktualisiert, um anzuzeigen, dass das Element gelöscht wurde:

Screenshot: Löschfunktion für Elemente in einem Container

Hinzufügen der Möglichkeit zum Hochladen von Dateien in den Container

Der letzte Schritt besteht darin, die Möglichkeit zum Hochladen von Dateien in einen Container oder einen Ordner innerhalb eines Containers hinzuzufügen.

Fügen Sie zunächst den folgenden Code unmittelbar vor dem // BOOKMARK 1 Kommentar hinzu:

const uploadFileRef = useRef<HTMLInputElement>(null);

Als Nächstes wiederholen wir eine ähnliche Technik, indem wir ein ausgeblendetes <Input> Steuerelement verwenden, um eine Datei hochzuladen. Fügen Sie den folgenden Code unmittelbar nach dem Öffnen <div> in der -Methode der Komponente return() hinzu:

<input ref={uploadFileRef} type="file" onChange={onUploadFileSelected} style={{ display: 'none' }} />

Fügen Sie der Symbolleiste eine Schaltfläche hinzu, um das Dateiauswahldialogfeld auszulösen. Fügen Sie dazu den folgenden Code unmittelbar nach der vorhandenen Symbolleistenschaltfläche hinzu, die einen neuen Ordner hinzufügt:

<ToolbarButton vertical icon={<ArrowUploadRegular />} onClick={onUploadFileClick}>Upload File</ToolbarButton>

Fügen Sie schließlich den folgenden Code unmittelbar vor dem // BOOKMARK 2 Kommentar hinzu, um zwei Ereignishandler hinzuzufügen. Der onUploadFileClick Handler wird ausgelöst, wenn Sie die Symbolleistenschaltfläche Datei hochladen auswählen, und der onUploadFileSelected Handler wird ausgelöst, wenn der Benutzer eine Datei auswählt:

const onUploadFileClick = () => {
  if (uploadFileRef.current) {
    uploadFileRef.current.click();
  }
};

const onUploadFileSelected = async (event: React.ChangeEvent<HTMLInputElement>) => {
  const file = event.target.files![0];
  const fileReader = new FileReader();
  fileReader.readAsArrayBuffer(file);
  fileReader.addEventListener('loadend', async (event: any) => {
    const graphClient = Providers.globalProvider.graph.client;
    const endpoint = `/drives/${props.container.id}/items/${folderId || 'root'}:/${file.name}:/content`;
    graphClient.api(endpoint).putStream(fileReader.result)
      .then(async (response) => {
        await loadItems(folderId || 'root');
      })
      .catch((error) => {
        console.error(`Failed to upload file ${file.name}: ${error.message}`);
      });
  });
  fileReader.addEventListener('error', (event: any) => {
    console.error(`Error on reading file: ${event.message}`);
  });
};

Testen Sie die Änderungen, indem Sie die Datei speichern, den Browser aktualisieren und die Schaltfläche Datei hochladen auswählen:

Screenshot der Schaltfläche

Nachdem Sie eine Datei ausgewählt haben, lädt die App die Datei hoch und aktualisiert die Tabelle des Containersinhalts:

Screenshot der neuen Datei, die im Container angezeigt wird.

Zusammenfassung

In dieser Übung haben Sie das vorhandene Projekt aktualisiert, um Dateien in einem SharePoint Embedded-Container zu speichern und zu verwalten.

Überprüfen Sie Ihre Kenntnisse

1.

Wie werden SharePoint Embedded-Container in Microsoft Graph implementiert?

2.

Wie erstellen Sie eine Datei in einem SharePoint Embedded-Container mit Microsoft Graph?

3.

Wie löschen Sie ein DriveItem in einem SharePoint Embedded-Container mithilfe von Microsoft Graph?