J'essaie actuellement de mettre en œuvre plusieurs tâches qui impliquent la liste, le téléchargement et le téléchargement de fichiers à partir d'un dossier OneDrive partagé. Ce dossier est accessible via les utilisateurs connectés OneDrive (visible dans son dossier racine). La partie liste fonctionne assez bien jusqu'à présent, en utilisant ce code:
string remoteDriveId = string.Empty;
private GraphServiceClient graphClient { get; set; }
// Get the root of the owners OneDrive
DriveItem ownerRoot = await this.graphClient.Drive.Root.Request().Expand("thumbnails,children($expand=thumbnails)").GetAsync();
// Select the shared folders general information
DriveItem sharedFolder = ownerRoot.Children.Where(c => c.Name == "sharedFolder").FirstOrDefault();
// Check if it is a remote folder
if(sharedFolder.Remote != null)
{
remoteDriveId = item.RemoteItem.ParentReference.DriveId;
// Get complete Information of the shared folder
sharedFolder = await graphClient.Drives[remoteDriveId].Items[sharedFolder.RemoteItem.Id].Request().Expand("thumbnails,children").GetAsync();
}
Donc, évidemment, je dois récupérer les informations des dossiers partagés du OneDrive qui les a partagées avec l'autre OneDrive. La partie suivante pour moi consiste à répertorier le contenu de ce dossier partagé, qui fonctionne également assez bien comme ceci:
foreach (DriveItem child in sharedFolder.Children)
{
DriveItem childItem = await graphClient.Drives[remoteDriveId].Items[child.Id].Request().Expand("thumbnails,children").GetAsync();
if(childItem.Folder == null)
{
string path = Path.GetTempPath() + Guid.NewGuid();
// Download child item to path
}
}
Mon problème commence avec la partie "Télécharger l'élément enfant vers le chemin". Là, je veux tout télécharger, ce n'est pas un dossier dans un fichier temporaire. Le problème est que OneDrive répond toujours à ma demande avec un message d'erreur, que le fichier est introuvable. Ce que j'ai essayé jusqu'à présent, c'est:
using (var stream = await graphClient.Drives[remoteDriveId].Items[childItem.Id].Content.Request().GetAsync())
using (var outputStream = new System.IO.FileStream(path, System.IO.FileMode.Create))
{
await stream.CopyToAsync(outputStream);
}
Dans une autre variante, j'ai essayé d'utiliser l'ID de childItem ParentReference (mais je pense que cela ne me mènera qu'à l'ID OneDrives distant de sharedFolder):
using (var stream = await graphClient.Drives[remoteDriveId].Items[childItem.ParentReference.Id].Content.Request().GetAsync())
using (var outputStream = new System.IO.FileStream(path, System.IO.FileMode.Create))
{
await stream.CopyToAsync(outputStream);
}
Après avoir téléchargé les fichiers, je veux les modifier et les re-télécharger vers un chemin différent dans le dossier partagé. Ce chemin est créé par moi (qui fonctionne déjà) comme ceci:
DriveItem folderToCreate = new DriveItem { Name = "folderName", Folder = new Folder() };
await graphClient.Drives[remoteDriveId].Items[sharedFolder.Id].Children.Request().AddAsync(folderToCreate);
Le téléchargement échoue alors. Je l'ai essayé comme ça:
using (var stream = new System.IO.FileStream(@"C:\temp\testfile.txt", System.IO.FileMode.Open))
{
await graphClient.Drives[remoteDriveId].Items[sharedFolder.Id].Content.Request().PutAsync<DriveItem>(stream);
}
Et aussi comme ça (qui fonctionne si ce n'est pas un dossier partagé et j'utilise donc Drive
au lieu de Drives
):
using (var stream = new System.IO.FileStream(@"C:\temp\testfile.txt", System.IO.FileMode.Open))
{
string folderPath = sharedFolder.ParentReference == null ? "" : sharedFolder.ParentReference.Path.Remove(0, 12) + "/" + Uri.EscapeUriString(sharedFolder.Name);
var uploadPath = folderPath + "/" + uploadFileName;
await graphClient.Drives[remoteDriveId].Root.ItemWithPath(uploadPath).Content.Request().PutAsync<DriveItem>(stream);
}
Je n'ai pas pu faire fonctionner la méthode AddAsync
(comme dans la création de dossier) car je ne sais pas comment créer un DriveItem
à partir d'un Stream
.
Si quelqu'un pouvait m'orienter dans la bonne direction, je l'apprécierais beaucoup! Je vous remercie!
La demande:
graphClient.Drives[remoteDriveId].Items[childItem.ParentReference.Id].Content.Request().GetAsync()
correspond à Télécharger le contenu d'un DriveItem endpoint et est uniquement valide si childItem.ParentReference.Id
fait référence à une ressource File
, dans un autre cas, elle échoue avec l'exception attendue:
Microsoft.Graph.ServiceException: Code: itemNotFound Message: vous ne pouvez pas obtenir le contenu d'un dossier
Donc, pour télécharger du contenu depuis un dossier la solution serait de:
GET /drives/{drive-id}/items/{folderItem-id}/children
driveItem
correspond à une facette File
: GET /drives/{drive-id}/items/{fileItem-id}/content
Exemple
var sharedItem = await graphClient.Drives[driveId].Items[folderItemId].Request().Expand(i => i.Children).GetAsync();
foreach (var item in sharedItem.Children)
{
if (item.File != null)
{
var fileContent = await graphClient.Drives[item.ParentReference.DriveId].Items[item.Id].Content.Request()
.GetAsync();
using (var fileStream = new FileStream(item.Name, FileMode.Create, System.IO.FileAccess.Write))
fileContent.CopyTo(fileStream);
}
}
Exemple 2
L'exemple montre comment télécharger un fichier à partir d'un dossier source et le télécharger dans un dossier cible:
var sourceDriveId = "--source drive id goes here--";
var sourceItemFolderId = "--source folder id goes here--";
var targetDriveId = "--target drive id goes here--";
var targetItemFolderId = "--target folder id goes here--";
var sourceFolder = await graphClient.Drives[sourceDriveId].Items[sourceItemFolderId].Request().Expand(i => i.Children).GetAsync();
foreach (var item in sourceFolder.Children)
{
if (item.File != null)
{
//1. download a file as a stream
var fileContent = await graphClient.Drives[item.ParentReference.DriveId].Items[item.Id].Content.Request()
.GetAsync();
//save it into file
//using (var fileStream = new FileStream(item.Name, FileMode.Create, System.IO.FileAccess.Write))
// fileContent.CopyTo(fileStream);
//2.Upload file into target folder
await graphClient.Drives[targetDriveId]
.Items[targetItemFolderId]
.ItemWithPath(item.Name)
.Content
.Request()
.PutAsync<DriveItem>(fileContent);
}
}
Au lieu de télécharger/télécharger le contenu du fichier, je pense que ce que vous recherchez réellement est DriveItem
copy
ou move
opérations . Disons qu'il y a des fichiers qui doivent être - copiés d'un dossier (source
) dans un autre (target
), puis l'exemple suivant montre comment l'accomplir :
var sourceDriveId = "--source drive id goes here--";
var sourceItemFolderId = "--source folder id goes here--";
var targetDriveId = "--target drive id goes here--";
var targetItemFolderId = "--target folder id goes here--";
var sourceFolder = await graphClient.Drives[sourceDriveId].Items[sourceItemFolderId].Request().Expand(i => i.Children).GetAsync();
foreach (var item in sourceFolder.Children)
{
if (item.File != null)
{
var parentReference = new ItemReference
{
DriveId = targetDriveId,
Id = targetItemFolderId
};
await graphClient.Drives[sourceDriveId].Items[item.Id]
.Copy(item.Name, parentReference)
.Request()
.PostAsync();
}
}
}