Arhn - архитектура программирования

Загрузка больших файлов для Office 365 (StartUpload, ContinueUpload, FinishUpload) не работает должным образом - SharePoint

Когда я пытаюсь загрузить большой файл с помощью 3 новых методов (StartUpload, ContinueUpload, FinishUpload), загружая фрагменты файла, то окончательный загруженный файл является поврежденным файлом, и размер также больше, чем фактический файл. Я использовал Rest API для загрузки больших файлов.

Выполняются следующие шаги: -

  1. Создайте HTML для входного файла.

<input name="FileUpload" type="file" id="uploadInput" className="inputFile" multiple="false" onchange="upload(this.files[0])" />

  1. Ниже приведен метод начальной точки кода:

    • Creating Global variable for siteurl

var Tasks = {
  urlName: window.location.origin + "/",
  siteName: '/sites/ABC',
};

  1. Вызов метода Upload ()

    • Сначала создайте фиктивный файл размером 0 в папке, чтобы продолжить загрузку большого файла.

    • Создайте объект FileReader, а затем начните создавать фрагменты файла с 3 параметрами (смещение, длина, метод (например, start / continue / finishupload)) и вставьте фрагменты в массив.

    • Создание уникального идентификатора для загрузки, например, uploadID
    • Вызов метода UploadFile

function upload(file) {
  var docLibraryName = "/sites/ABC/Shared Documents";
  var fileName = $("#uploadInput").val().replace(/C:\\fakepath\\/i, '');
  var folderName = "";
  createDummaryFile(docLibraryName, fileName, folderName)
  var fr = new FileReader();
  var offset = 0;
  var total = file.size;
  var length = 1000000 > total ? total : 1000000;
  var chunks = [];
  fr.onload = evt => {
    while (offset < total) {
      if (offset + length > total)
        length = total - offset;
      chunks.push({
        offset,
        length,
        method: getUploadMethod(offset, length, total)
      });
      offset += length;
    }
    for (var i = 0; i < chunks.length; i++)
      console.log(chunks[i]);
    if (chunks.length > 0) {
      const id = getGuid();
      uploadFile(evt.target.result, id, docLibraryName, fileName, chunks, 0);
    }
  };
  fr.readAsArrayBuffer(file);
}

function createDummaryFile(libraryName, fileName, folderName) {
  return new Promise((resolve, reject) => {
    var endpoint = Tasks.urlName + Tasks.siteName + "/_api/web/GetFolderByServerRelativeUrl('" + libraryName + "/" + folderName + "')/Files/add(url=@TargetFileName,overwrite='true')?" +
      "&@TargetFileName='" + fileName + "'";
    var url;
    const headers = {
      "accept": "application/json;odata=verbose"
    };
    performUpload(endpoint, headers, libraryName, fileName, folderName, convertDataBinaryString(0));
  });
}

function S4() {
  return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
}

function getGuid() {
  return (S4() + S4() + "-" + S4() + "-4" + S4().substr(0, 3) + "-" + S4() + "-" + S4() + S4() + S4()).toLowerCase();
}
//check position for selecting method

function getUploadMethod(offset, length, total) {
  if (offset + length + 1 > total) {
    return 'finishupload';
  } else if (offset === 0) {
    return 'startupload';
  } else if (offset < total) {
    return 'continueupload';
  }
  return null;
}

  1. Метод загрузки файла

    • Преобразуйте буфер массива в блоки больших двоичных объектов, чтобы начать загрузку файла

    • Начните фактическую загрузку фрагментов файлов, используя методы и смещение в 1 МБ, которые мы создали ранее (метод uploadFileChunk)

    • Запустить цикл для фрагмента и вызвать тот же метод

function uploadFile(result, id, libraryPath, fileName, chunks, index) {
  const data = convertFileToBlobChunks(result, chunks[index]);
  var response = uploadFileChunk(id, libraryPath, fileName, chunks[index], data);
  index += 1;
  if (index < chunks.length)
    uploadFile(result, id, libraryPath, fileName, chunks, index, chunks[index].offset);
}

function convertFileToBlobChunks(result, chunkInfo) {
  var arrayBuffer = chunkInfo.method === 'finishupload' ? result.slice(chunkInfo.offset) : result.slice(chunkInfo.offset, chunkInfo.offset + chunkInfo.length);
  return convertDataBinaryString(arrayBuffer);
}

function convertDataBinaryString(data) {
  var fileData = '';
  var byteArray = new Uint8Array(data);
  for (var i = 0; i < byteArray.byteLength; i++) {
    fileData += String.fromCharCode(byteArray[i]);
  }
  return fileData;
}

  1. UploadFileChunk, чтобы начать загрузку фрагментов файлов)

    • Form string if startupload then no fileoffset and if continueupload and finishupload then it will have fileoffset.
    • Вызов метода performupload, чтобы начать загрузку с использованием rest api

function uploadFileChunk(id, libraryPath, fileName, chunk, data) {
  new Promise((resolve, reject) => {
    var offset = chunk.offset === 0 ? '' : ',fileOffset=' + chunk.offset;
    var folderName = "";
    var endpoint = Tasks.urlName + Tasks.siteName + "/_api/web/getfilebyserverrelativeurl('" + libraryPath + "/" + fileName + "')/" + chunk.method + "(uploadId=guid'" + id + "'" + offset + ")";
    const headers = {
      "Accept": "application/json; odata=verbose",
      "Content-Type": "application/octet-stream"
    };
    performUpload(endpoint, headers, libraryPath, fileName, folderName, data);
  });
}

function performUpload(endpoint, headers, libraryName, fileName, folderName, fileData) {
  new Promise((resolve, reject) => {
    var digest = $("#__REQUESTDIGEST").val();
    $.ajax({
      url: endpoint,
      async: false,
      method: "POST",
      headers: headers,
      data: fileData,
      binaryStringRequestBody: true,
      success: function(data) {},
      error: err => reject(err.responseText)
    });
  });
}

Пожалуйста, подскажите, почему загруженный файл поврежден и имеет размер меньше или больше фактического?

Заранее спасибо.


Ответы:


1

У меня была такая же проблема с этим кодом. Я изменил convertFileToBlobChunks, чтобы просто вернуть ArrayBuffer.

function convertFileToBlobChunks(result, chunkInfo) {
  var arrayBuffer = chunkInfo.method === 'finishupload' ? 
  result.slice(chunkInfo.offset) : result.slice(chunkInfo.offset, chunkInfo.offset + chunkInfo.length);

  return arrayBuffer;
}

Я тоже убрал "Content-Type": "application/octet-stream" из шапки.

После этого он загрузился нормально.

22.02.2018
  • Мне также пришлось добавить processData: false в запрос ajax. 12.06.2019
  • Новые материалы

    Коллекции публикаций по глубокому обучению
    Последние пару месяцев я создавал коллекции последних академических публикаций по различным подполям глубокого обучения в моем блоге https://amundtveit.com - эта публикация дает обзор 25..

    Представляем: Pepita
    Фреймворк JavaScript с открытым исходным кодом Я знаю, что недостатка в фреймворках JavaScript нет. Но я просто не мог остановиться. Я хотел написать что-то сам, со своими собственными..

    Советы по коду Laravel #2
    1-) Найти // You can specify the columns you need // in when you use the find method on a model User::find(‘id’, [‘email’,’name’]); // You can increment or decrement // a field in..

    Работа с временными рядами спутниковых изображений, часть 3 (аналитика данных)
    Анализ временных рядов спутниковых изображений для данных наблюдений за большой Землей (arXiv) Автор: Рольф Симоэс , Жильберто Камара , Жильберто Кейрос , Фелипе Соуза , Педро Р. Андраде ,..

    3 способа решить квадратное уравнение (3-й мой любимый) -
    1. Методом факторизации — 2. Используя квадратичную формулу — 3. Заполнив квадрат — Давайте поймем это, решив это простое уравнение: Мы пытаемся сделать LHS,..

    Создание VR-миров с A-Frame
    Виртуальная реальность (и дополненная реальность) стали главными модными терминами в образовательных технологиях. С недорогими VR-гарнитурами, такими как Google Cardboard , и использованием..

    Демистификация рекурсии
    КОДЕКС Демистификация рекурсии Упрощенная концепция ошеломляющей О чем весь этот шум? Рекурсия, кажется, единственная тема, от которой у каждого начинающего студента-информатика..