Ошибка при загрузке файла с использованием Microsoft Graph API

#api #file-upload #microsoft-graph-api #onedrive #microsoft-graph-sdks

#API #загрузка файла #microsoft-graph-api #onedrive #microsoft-graph-sdks

Вопрос:

Я пытаюсь загрузить большой файл на один диск с помощью Microsoft Graph API. Загрузка на один диск работает нормально, но файл поврежден. Пожалуйста, помогите мне решить проблему.

 public ActionResult UploadLargeFiles(string id, [FromForm]IFormFile files)
    {
        string fileName = files.FileName;
        int fileSize = Convert.ToInt32(files.Length);

        var uploadProvider = new JObject();
        var res = new JArray();

        var isExistence = _mailService.GetUploadFolder(id);
        if (isExistence != HttpStatusCode.OK)
        {
            var createFolder = _mailService.CreateUploadFolder(id);
            if (createFolder != HttpStatusCode.Created)
            {
                return BadRequest(ModelState);
            }
        }

        if (files.Length > 0)
        {
            var uploadSessionUrl = _mailService.CreateUploadSession(id, fileName);
            if (uploadSessionUrl != null)
            {
                if (fileSize < 4194304)
                {
                    uploadProvider = _mailService.UploadByteFile(id, uploadSessionUrl, files);
                    res.Add(uploadProvider);
                }
            }
            else
            {
                return BadRequest(ModelState);
            }
        }

        return Ok();
    }
  
  1. createUploadSession

      public string CreateUploadSession(string upn, string fileName)
     {
         var uploadSession = _mailGraphService.CreateUploadSession(upn, fileName).Resu<
         var sessionResult = new UploadSessionDTO(uploadSession);
    
         return sessionResult.uploadUrl;
     }
    
     public async Task<UploadSessionDTO> CreateUploadSession(string upn, string fileName)
     {
         this.InitHttpClient();
    
         var jObject = JObject.FromObject(new { item = new Dictionary<string, object> { { "@microsoft.graph.conflictBehavior", "rename" } }, fileSystemInfo = new Dictionary<string, object> { { "@odata.type", "microsoft.graph.fileSystemInfo" } }, name = fileName });
         var toJson = JsonConvert.SerializeObject(jObject);
         var content = new StringContent(toJson, Encoding.UTF8, "application/json");
    
         var response = await _client.PostAsync("users/"  upn   "/drive/root:/MailFiles/"   fileName  ":/createUploadSession", content);
         if (!response.IsSuccessStatusCode)
             return null;
    
         var strData = await response.Content.ReadAsStringAsync();
         dynamic uploadSession = JsonConvert.DeserializeObject<UploadSessionDTO>(strData);
    
         return uploadSession;
     }
    
    
     public JObject LargeFileUpload(string upn, string url, IFormFile files)
     {
         var responseCode = HttpStatusCode.OK;
         var jObject = new JObject();
    
         int idx = 0;
         int fileSize = Convert.ToInt32(files.Length);
         int fragSize = 4 * 1024 * 1024; //4MB => 4 * 1024 * 1024;
         var byteRemaining = fileSize;
         var numFragments = (byteRemaining / fragSize)   1;
    
         while (idx < numFragments)
         {
             var chunkSize = fragSize;
             var start = idx * fragSize;
             var end = idx * fragSize   chunkSize - 1;
             var offset = idx * fragSize;
    
             if (byteRemaining < chunkSize)
             {
                 chunkSize = byteRemaining;
                 end = fileSize - 1;
             }
    
             var contentRange = " bytes "   start   "-"   end   "/"   fileSize;
             byte[] file = new byte[chunkSize];
             using (var client = new HttpClient())
             {
                 var content = new ByteArrayContent(file);
                 content.Headers.Add("Content-Length", chunkSize.ToString());
                 content.Headers.Add("Content-Range", contentRange);
    
                 var response = client.PutAsync(url, content);
                 var strData = response.Result.Content.ReadAsStringAsync().Resu<
                 responseCode = response.Result.StatusCode;
    
                 //업로드 성공
                 if (responseCode == HttpStatusCode.Created)
                 {
                     JObject data = JObject.Parse(strData);
                     string downloadUrl = data["@content.downloadUrl"].ToString();
                     string itemId = data["id"].ToString();
    
                     //파일 크기 -> kb로 변환
                     fileSize = fileSize / 1000;
                     jObject = JObject.FromObject(new { name = files.Name, id = itemId, url = downloadUrl, size = (double)fileSize });
                 }
                 //업로드 충돌
                 else if (responseCode == HttpStatusCode.Conflict)
                 {
                     var restart = RestartByteFile(upn, url, files.Name);
                     responseCode = restart;
                 }
             }
             byteRemaining = byteRemaining - chunkSize;
             idx  ;
         }
    
         if (responseCode == HttpStatusCode.Created) { return jObject; }
         else return jObject = JObject.FromObject(new { result = "실패" });
     }
      

Когда я проверил OneDrive, файл был загружен нормально, а когда я загрузил и открыл файл, он оказался поврежденным файлом.

Интересно, почему файл повреждается при загрузке и как это исправить. Если проблема не может быть решена, пожалуйста, сообщите нам, что она не может быть решена.

Комментарии:

1. (1) Вы пытались вручную загрузить файл в onedrive, и у вас все еще работает? (2) Помимо вашего кода, вы пытались загрузить файл с помощью MS Graph Explorer или POSTMAN? Работает ли это для вас?

2. @Dev (1) При загрузке вручную файл загружается нормально. (2) Работает снаружи.

3. Если он работает снаружи, то это не проблема с вызовом Graph API, но я подозреваю, что это может быть связано с приведенным выше кодом / логикой или проверкой правильности установки / передачи необходимых заголовков, правильного размера вложений — аналогично тому, что вы делаете с POSTMAN / MS Graph Explorer. Дайте мне знать, как это происходит.

4. @Dev (1) Размер вложенного файла не имеет значения. Загружаются и повреждаются даже маленькие и большие файлы. (2) Как мне передать файл, преобразованный в байты, в качестве заголовка при передаче с использованием Postman или MS Graph API? В коде я могу преобразовать его и сразу передать, но как мне преобразовать его в байты случайным образом и вызвать его из graph API? (3) При методе прямой передачи без создания сеанса загрузки файл загружается, но он поврежден. В этом случае возникает ошибка в части преобразования файла в байты?

5. Когда я попытался повторить проблему, я не смог увидеть ваше поведение. При этом я помню связанную с этим тему. Посмотрите, что вы знаете об этом, и попробуйте доступный в нем пример кода, чтобы узнать, поможет ли он вам продвинуться вперед — github.com/microsoftgraph/msgraph-sdk-dotnet/issues/493