@accountnujen

Почему файл из github постоянно на ~37% больше, чем указан?

Я пытаюсь смастерить функцию скачивания с прогрессом. Мне нужно получать прогресс в процентах. Я загрузил 3 файла на github: 5mb.txt 10mb.txt и 20mb.txt. Их я пытаюсь прочитать.

Так как при прямом обращении к файлу через api я не могу получить его содержимое (так работает api github), то получение содержимого происходит в 2 этапа. Первый запрос на файл,а затем на blob. При первом запросе я получаю его размер, который соответствует 5000000 (5мб) и ссылку на blob. Следом, когда я делаю запрос на blob и смотрю прогресс загрузки, то я получаю каждый раз в результате ~137%.

Когда я получаю blob, то я не получаю конкретно файл, а так же, как и в первом случае, получаю json объект, где в ключе content находится мой файл. Разумеется размер blob запроса не будет на 100% соответствовать значению size из первого запроса, так как во втором запросе мне также возвращаются другие ключи (encoding, sha, size, node_id, url). Но эти ключи каждый раз имеют плюс минус одинаковый размер, поэтому они сразу отметаются.

В случае скачивания файла на
5мб - я получаю 6889205 байт
10мб - 13778096 байт
20мб - 27555872 байт
Каждый раз полученный размер на ~37% больше, чем заданный. Вот откуда он в последнем файле взял 7мб?

Код можете запустить из консоли
Код

function makeRequest(method, url, data = false) {
  return new Promise(function(resolve, reject) {
    var xhr = new XMLHttpRequest();
    xhr.open(method, url, true);
    xhr.setRequestHeader('Content-Type', 'application/json');
    
    xhr.upload.onprogress = function(event) {
     if (event.lengthComputable) {
       var percentComplete = (event.loaded / event.total) * 100;
       console.log('Прогресс загрузки:', percentComplete.toFixed(2) + '%');
     }
    };

    if (method = 'GET' && data) {
      xhr.onprogress = (event) => {
        let percentComplete = (event.loaded / data) * 100;
        console.log(`Получено с сервера ${percentComplete}%. загружено ${event.loaded}`);
      }
    }
    

    xhr.onload = function() {
      if (xhr.status >= 200 && xhr.status < 300) {
        resolve(JSON.parse(xhr.response));
      } else {
        reject(xhr.statusText);
      }
    };
    
    xhr.onerror = function() {
      reject(xhr.statusText);
    };
    
    if (data && method === 'PUT') {
      xhr.setRequestHeader('Content-Type', 'application/json;charset=UTF-8');
      xhr.send(JSON.stringify(data));
    } else {
      xhr.send();
    }
  });
}


  makeRequest('GET', "https://api.github.com/repos/accountnujen/testa/contents/10mb.txt")
    .then(data => {
      console.log(data);
      let size = data.size;
      makeRequest('GET',data.git_url,size)
        .then(data => {
          console.log(data);
        })
    }).catch(error => {
      console.log(error);
    })

  • Вопрос задан
  • 232 просмотра
Решения вопроса 2
Rsa97
@Rsa97
Для правильного вопроса надо знать половину ответа
А вы сами то открывали файл по ссылке из data.git_url?
Там отдаётся JSON с файлом, закодированным в Base64.
В Base64 каждые 6 бит исходного файла кодируются одним символом (8 бит) текста, а после каждых 60 символов добавляется символ переноса строки. Вот и получаем ~ (2/6 + 8/360) = 35.6% дополнительно к объёму.
Если хотите получить файл сам по себе, то используйте поле download_url.
Ответ написан
vesper-bot
@vesper-bot
Любитель файрволлов
Файл передается поверх HTML скорее всего в виде base64-encoded, то есть 8 байт передачи на каждые 6 байт файла. При этом может быть попытаться переданным в сжатом виде, но если там случайный текст, сжаться у него не выйдет и передано будет больше, чем принято. Проанализируйте заголовки, в особенности Content-type, что именно прилетает и в каком виде. А чтобы корректно посчитать прогресс, тяните Content-Length если его API передает (если нет, то шиш вам).
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
Sanasol
@Sanasol Куратор тега JavaScript
нельзя просто так взять и загуглить ошибку
event.loaded / data
ничего что на boolean делится?

event.total = 0 поэтому весь прогресс примерный и вероятно на скорость загрузки ориентируется, а точнее на то что браузер решит.

https://developer.mozilla.org/en-US/docs/Web/API/P...
If the event's lengthComputable property is false, this value is meaningless and should be ignored


lengthComputable = false

Почему: https://stackoverflow.com/a/47287125/1603055
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы