Как мне отправить последние байты для сеанса загрузки Microsoft Graph?

#c# #azure #file-upload #microsoft-graph-api

#c# #azure #загрузка файла #microsoft-graph-api

Вопрос:

Я следую документу, предоставленному Microsoft для загрузки больших файлов в Microsoft Graph.
Все работает отлично, за исключением массива байтов в последних байтах файла.

https://docs.microsoft.com/en-us/graph/api/driveitem-createuploadsession?view=graph-rest-1.0

Сначала я создаю элемент DriveItem с именем файла и загружаю пустой байт[] .

 using (var emptyFileClient = new HttpClient())
{
   var url = "https://graph.microsoft.com/v1.0/drives/"   driveID   "/root:/"   sharepoint2013ID   "/"   fileInfo.Name   ":/content";
   emptyFileClient.DefaultRequestHeaders.Add("Authorization", bearer);
   var emptyFileContent = new ByteArrayContent(new byte[0]);
                
   var emptyFileResponse = emptyFileClient.PutAsync(url, emptyFileContent).Resu<
   if (emptyFileResponse.StatusCode != System.Net.HttpStatusCode.Created)
   {
      return false;
   }
}
 

Затем я удостоверяюсь, что у меня есть действительный DriveItemID

 var client = new RestClient("https://graph.microsoft.com/v1.0/drives/"   driveID   "/root:/"   sharepoint2013ID   "/"   fileInfo.Name);
var request = new RestRequest(Method.GET);
request.AddHeader("Authorization", bearer);
IRestResponse response = client.Execute(request);
if (response.StatusCode != System.Net.HttpStatusCode.OK)
{
    return null;
}
 

Затем я создаю UploadSession

 //Create UploadSession
var client = new RestClient("https://graph.microsoft.com/v1.0/drives/"   driveID   "/items/"   driveItem.id   "/createUploadSession");
var request = new RestRequest(Method.POST);
request.AddHeader("Authorization", bearer);
IRestResponse response = client.Execute(request);
if (response.StatusCode != System.Net.HttpStatusCode.OK)
{
   throw new Exception("Could Not Create Upload Session");
}
 

Это работает правильно, поэтому теперь я начинаю загружать файл.
Опять же, все работает правильно до последнего байта [] .

Я проверил, что ожидаемый диапазон для последнего байта [] соответствует массиву байтов, который я отправляю.

 WebRequest request = null;
using (Stream source = File.OpenRead(fileInfo.FullName))
{
    double fileSizeBytes = fileInfo.Length;
    int bufferSize = 2048000;
    byte[] buffer = new byte[bufferSize];
    int bytesRead;
    var loopCount = 0;
    while ((bytesRead = source.Read(buffer, 0, buffer.Length)) > 0)
    {
        double startByte = bufferSize * loopCount;
        double endByte = startByte   bytesRead - 1;
        var contentRange = "bytes "   startByte   "-"   endByte   "/"   fileSizeBytes;
        Console.WriteLine(contentRange);

        request = WebRequest.Create(uploadSession.uploadUrl);
        request.Headers.Add("Authorization", bearer);
        request.Headers.Add("Content-Length", bytesRead.ToString());
        request.Headers.Add("Content-Range", contentRange);
        request.Method = "PUT";
        request.ContentLength = buffer.Length;
        Stream dataStream = request.GetRequestStream();
        dataStream.Write(buffer, 0, buffer.Length);
        dataStream.Close();
                    
        var response = (HttpWebResponse)request.GetResponse();
        if (response.StatusCode != System.Net.HttpStatusCode.Accepted)
        {
            return false;
        }
        loopCount  ;
    }
}
 

Я тестировал большие файлы, размер которых превышает размер буфера, чтобы разделить загрузку на несколько запросов. Вы также можете протестировать файлы меньшего размера, если уменьшите размер буфера. Буду признателен за любую помощь по этому вопросу.

Также я не заинтересован в использовании графика.SDK или любая другая библиотека, это должно выполняться из веб-запросов. Это для гибридного решения, в котором сервер Sharepoint2013 будет сохранять некоторые файлы в SharepointOnline.

Ответ №1:

Проблема оказалась в том, что я дважды устанавливал заголовок content-length, и один из них использовал неверное значение. Просто закомментируйте следующую строку, и все, что указано выше, будет работать правильно.

//запрос.Длина содержимого = буфер.Длина;

При окончательной загрузке длина не равна полной длине буфера, вместо этого необходимо установить значение bytesRead .