Charger des fichiers volumineux à l’aide des Kits de développement logiciel (SDK) Microsoft Graph
Article
Un certain nombre d’entités dans Microsoft Graph prennent en charge les chargements de fichiers pouvant être repris pour faciliter le chargement de fichiers volumineux. Au lieu d’essayer de charger l’intégralité du fichier dans une seule requête, le fichier est divisé en morceaux plus petits et une requête est utilisée pour charger une seule tranche. Pour simplifier ce processus, les sdk Microsoft Graph implémentent une tâche de chargement de fichiers volumineux qui gère le chargement des tranches.
using var fileStream = File.OpenRead(filePath);
// Use properties to specify the conflict behavior
// using DriveUpload = Microsoft.Graph.Drives.Item.Items.Item.CreateUploadSession;
var uploadSessionRequestBody = new DriveUpload.CreateUploadSessionPostRequestBody
{
Item = new DriveItemUploadableProperties
{
AdditionalData = new Dictionary<string, object>
{
{ "@microsoft.graph.conflictBehavior", "replace" },
},
},
};
// Create the upload session
// itemPath does not need to be a path to an existing item
var myDrive = await graphClient.Me.Drive.GetAsync();
var uploadSession = await graphClient.Drives[myDrive?.Id]
.Items["root"]
.ItemWithPath(itemPath)
.CreateUploadSession
.PostAsync(uploadSessionRequestBody);
// Max slice size must be a multiple of 320 KiB
int maxSliceSize = 320 * 1024;
var fileUploadTask = new LargeFileUploadTask<DriveItem>(
uploadSession, fileStream, maxSliceSize, graphClient.RequestAdapter);
var totalLength = fileStream.Length;
// Create a callback that is invoked after each slice is uploaded
IProgress<long> progress = new Progress<long>(prog =>
{
Console.WriteLine($"Uploaded {prog} bytes of {totalLength} bytes");
});
try
{
// Upload the file
var uploadResult = await fileUploadTask.UploadAsync(progress);
Console.WriteLine(uploadResult.UploadSucceeded ?
$"Upload complete, item ID: {uploadResult.ItemResponse.Id}" :
"Upload failed");
}
catch (ODataError ex)
{
Console.WriteLine($"Error uploading: {ex.Error?.Message}");
}
// Get an input stream for the file
File file = new File(filePath);
InputStream fileStream = new FileInputStream(file);
long streamSize = file.length();
// Set body of the upload session request
CreateUploadSessionPostRequestBody uploadSessionRequest = new CreateUploadSessionPostRequestBody();
DriveItemUploadableProperties properties = new DriveItemUploadableProperties();
properties.getAdditionalData().put("@microsoft.graph.conflictBehavior", "replace");
uploadSessionRequest.setItem(properties);
// Create an upload session
// ItemPath does not need to be a path to an existing item
String myDriveId = graphClient.me().drive().get().getId();
UploadSession uploadSession = graphClient.drives()
.byDriveId(myDriveId)
.items()
.byDriveItemId("root:/"+itemPath+":")
.createUploadSession()
.post(uploadSessionRequest);
// Create the upload task
int maxSliceSize = 320 * 10;
LargeFileUploadTask<DriveItem> largeFileUploadTask = new LargeFileUploadTask<>(
graphClient.getRequestAdapter(),
uploadSession,
fileStream,
streamSize,
maxSliceSize,
DriveItem::createFromDiscriminatorValue);
int maxAttempts = 5;
// Create a callback used by the upload provider
IProgressCallback callback = (current, max) -> System.out.println(
String.format("Uploaded %d bytes of %d total bytes", current, max));
// Do the upload
try {
UploadResult<DriveItem> uploadResult = largeFileUploadTask.upload(maxAttempts, callback);
if (uploadResult.isUploadSuccessful()) {
System.out.println("Upload complete");
System.out.println("Item ID: " + uploadResult.itemResponse.getId());
} else {
System.out.println("Upload failed");
}
} catch (CancellationException ex) {
System.out.println("Error uploading: " + ex.getMessage());
}
// Create a file stream
$file = GuzzleHttp\Psr7\Utils::streamFor(fopen($filePath, 'r'));
// Create the upload session request
$uploadProperties = new Models\DriveItemUploadableProperties();
$uploadProperties->setAdditionalData([
'@microsoft.graph.conflictBehavior' => 'replace'
]);
// use Microsoft\Graph\Generated\Drives\Item\Items\Item\CreateUploadSession\CreateUploadSessionPostRequestBody
// as DriveItemCreateUploadSessionPostRequestBody;
$uploadSessionRequest = new DriveItemCreateUploadSessionPostRequestBody();
$uploadSessionRequest->setItem($uploadProperties);
// Create the upload session
/** @var Models\Drive $drive */
$drive = $graphClient->me()->drive()->get()->wait();
$uploadSession = $graphClient->drives()
->byDriveId($drive->getId())
->items()
->byDriveItemId('root:/'.$itemPath.':')
->createUploadSession()
->post($uploadSessionRequest)
->wait();
$largeFileUpload = new LargeFileUploadTask($uploadSession, $graphClient->getRequestAdapter(), $file);
$totalSize = $file->getSize();
$progress = fn($prog) => print('Uploaded '.$prog[1].' of '.$totalSize.' bytes'.PHP_EOL);
try {
$largeFileUpload->upload($progress)->wait();
} catch (\Psr\Http\Client\NetworkExceptionInterface $ex) {
$largeFileUpload->resume()->wait();
}
// readFile from fs/promises
const file = await readFile(filePath);
// basename from path
const fileName = basename(filePath);
const options: OneDriveLargeFileUploadOptions = {
// Relative path from root folder
path: targetFolderPath,
fileName: fileName,
rangeSize: 1024 * 1024,
uploadEventHandlers: {
// Called as each "slice" of the file is uploaded
progress: (range, _) => {
console.log(`Uploaded bytes ${range?.minValue} to ${range?.maxValue}`);
},
},
};
// Create FileUpload object
const fileUpload = new FileUpload(file, fileName, file.byteLength);
// Create a OneDrive upload task
const uploadTask = await OneDriveLargeFileUploadTask.createTaskWithFileObject(
graphClient,
fileUpload,
options,
);
// Do the upload
const uploadResult: UploadResult = await uploadTask.upload();
// The response body will be of the corresponding type of the
// item being uploaded. For OneDrive, this is a DriveItem
const driveItem = uploadResult.responseBody as DriveItem;
console.log(`Uploaded file with ID: ${driveItem.id}`);
Reprise du chargement d’un fichier
Les Kits de développement logiciel (SDK) Microsoft Graph prennent en charge la reprise des chargements en cours. Si votre application rencontre une interruption de connexion ou une status HTTP 5.x.x lors du chargement, vous pouvez reprendre le chargement.
// Create message
var draftMessage = new Message
{
Subject = "Large attachment",
};
var savedDraft = await graphClient.Me
.Messages
.PostAsync(draftMessage);
using var fileStream = File.OpenRead(filePath);
var largeAttachment = new AttachmentItem
{
AttachmentType = AttachmentType.File,
Name = Path.GetFileName(filePath),
Size = fileStream.Length,
};
// using AttachmentUpload = Microsoft.Graph.Me.Messages.Item.Attachments.CreateUploadSession;
var uploadSessionRequestBody = new AttachmentUpload.CreateUploadSessionPostRequestBody
{
AttachmentItem = largeAttachment,
};
var uploadSession = await graphClient.Me
.Messages[savedDraft?.Id]
.Attachments
.CreateUploadSession
.PostAsync(uploadSessionRequestBody);
// Max slice size must be a multiple of 320 KiB
int maxSliceSize = 320 * 1024;
var fileUploadTask =
new LargeFileUploadTask<FileAttachment>(uploadSession, fileStream, maxSliceSize);
var totalLength = fileStream.Length;
// Create a callback that is invoked after each slice is uploaded
IProgress<long> progress = new Progress<long>(prog =>
{
Console.WriteLine($"Uploaded {prog} bytes of {totalLength} bytes");
});
try
{
// Upload the file
var uploadResult = await fileUploadTask.UploadAsync(progress);
Console.WriteLine(uploadResult.UploadSucceeded ? "Upload complete" : "Upload failed");
}
catch (ODataError ex)
{
Console.WriteLine($"Error uploading: {ex.Error?.Message}");
}
// Create message
Message draftMessage = new Message();
draftMessage.setSubject("Large attachment");
Message savedDraft = graphClient.me().messages().post(draftMessage);
// Get an input stream for the file
File file = new File(filePath);
InputStream fileStream = new FileInputStream(file);
long streamSize = file.length();
final AttachmentItem largeAttachment = new AttachmentItem();
largeAttachment.setAttachmentType(AttachmentType.File);
largeAttachment.setName(file.getName());
largeAttachment.setSize(streamSize);
com.microsoft.graph.users.item.messages.item.attachments.createuploadsession.CreateUploadSessionPostRequestBody uploadRequestBody
= new com.microsoft.graph.users.item.messages.item.attachments.createuploadsession.CreateUploadSessionPostRequestBody();
uploadRequestBody.setAttachmentItem(largeAttachment);
final UploadSession uploadSession = graphClient.me()
.messages()
.byMessageId(savedDraft.getId())
.attachments()
.createUploadSession()
.post(uploadRequestBody);
LargeFileUploadTask<FileAttachment> largeFileUploadTask = new LargeFileUploadTask<>(
graphClient.getRequestAdapter(),
uploadSession,
fileStream,
streamSize,
FileAttachment::createFromDiscriminatorValue);
int maxAttempts = 5;
// Create a callback used by the upload provider
IProgressCallback callback = (current, max) -> System.out.println(
String.format("Uploaded %d bytes of %d total bytes", current, max));
// Do the upload
try {
UploadResult<FileAttachment> uploadResult = largeFileUploadTask.upload(maxAttempts, callback);
if (uploadResult.isUploadSuccessful()) {
System.out.println("Upload complete");
System.out.println("Item ID: " + uploadResult.itemResponse.getId());
} else {
System.out.println("Upload failed");
}
} catch (CancellationException ex) {
System.out.println("Error uploading: " + ex.getMessage());
}
// Create a message
$draftMessage = new Models\Message();
$draftMessage->setSubject('Large attachment');
/** @var Models\Message $savedDraft */
$savedDraft = $graphClient->me()
->messages()
->post($draftMessage)
->wait();
// Create a file stream
$file = GuzzleHttp\Psr7\Utils::streamFor(fopen($filePath, 'r'));
// Create an attachment
$attachment = new Models\AttachmentItem();
$attachment->setAttachmentType(new Models\AttachmentType(Models\AttachmentType::FILE));
$attachment->setName(basename($filePath));
$attachment->setSize($file->getSize());
// use Microsoft\Graph\Generated\Users\Item\Messages\Item\Attachments\CreateUploadSession\CreateUploadSessionPostRequestBody
// as AttachmentCreateUploadSessionPostRequestBody;
$uploadSessionRequest = new AttachmentCreateUploadSessionPostRequestBody();
$uploadSessionRequest->setAttachmentItem($attachment);
// Create the upload session
$uploadSession = $graphClient->me()
->messages()
->byMessageId($savedDraft->getId())
->attachments()
->createUploadSession()
->post($uploadSessionRequest)
->wait();
$largeFileUpload = new LargeFileUploadTask($uploadSession, $graphClient->getRequestAdapter(), $file);
$totalSize = $file->getSize();
$progress = fn($prog) => print('Uploaded '.$prog[1].' of '.$totalSize.' bytes'.PHP_EOL);
try {
$largeFileUpload->upload($progress)->wait();
} catch (\Psr\Http\Client\NetworkExceptionInterface $ex) {
$largeFileUpload->resume()->wait();
}
// readFile from fs/promises
const file = await readFile(filePath);
// basename from path
const fileName = basename(filePath);
const options: LargeFileUploadTaskOptions = {
rangeSize: 1024 * 1024,
uploadEventHandlers: {
// Called as each "slice" of the file is uploaded
progress: (range, _) => {
console.log(`Uploaded bytes ${range?.minValue} to ${range?.maxValue}`);
},
},
};
// Create a draft message
const message: Message = await graphClient.api('/me/messages').post({
subject: 'Large file attachment',
});
// Create upload session using draft message's ID
const uploadUrl = `/me/messages/${message.id}/attachments/createUploadSession`;
const uploadSession = await LargeFileUploadTask.createUploadSession(
graphClient,
uploadUrl,
{
AttachmentItem: {
attachmentType: 'file',
name: fileName,
size: file.byteLength,
},
},
);
// Create file upload
const fileUpload = new FileUpload(file, fileName, file.byteLength);
// Create upload task
const uploadTask = new LargeFileUploadTask(
graphClient,
fileUpload,
uploadSession,
options,
);
// Upload the file
const uploadResult = await uploadTask.upload();
console.log(`File uploaded to ${uploadResult.location}`);
Bientôt disponible : Tout au long de 2024, nous allons supprimer progressivement GitHub Issues comme mécanisme de commentaires pour le contenu et le remplacer par un nouveau système de commentaires. Pour plus d’informations, consultez https://aka.ms/ContentUserFeedback.