Как вычислить хэш файл md5 файла с помощью javascript

Есть ли способ вычислить хэш MD5 файла перед загрузкой на сервер с помощью Javascript?

Ответ 1

Несмотря на то, что JS-реализации алгоритма MD5, старые браузеры, как правило, не могут читать файлы из локальной файловой системы.

Я написал это в 2009 году. Так как насчет новых браузеров?

В браузере, поддерживающем FileAPI, вы можете * прочитать содержимое файла - пользователь должен выбрать его либо с элементом <input>, либо с перетаскиванием. Начиная с января 2013 года, вот как складываются основные браузеры:

Ответ 2

Я создал библиотеку, которая реализует инкрементный md5, чтобы эффективно обрабатывать большие файлы. В основном вы читаете файл в кусках (чтобы сохранить низкую память) и хэш его постепенно. У вас есть основное использование и примеры в readme.

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

https://github.com/satazor/SparkMD5

Ответ 3

довольно просто вычислить хеш MD5, используя функцию MD5 CryptoJS и HTML5 FileReader API. В следующем фрагменте кода показано, как вы можете прочитать двоичные данные и вычислить хеш MD5 по изображению, которое было перетащено в ваш браузер:

var holder = document.getElementById('holder');

holder.ondragover = function() {
  return false;
};

holder.ondragend = function() {
  return false;
};

holder.ondrop = function(event) {
  event.preventDefault();

  var file = event.dataTransfer.files[0];
  var reader = new FileReader();

  reader.onload = function(event) {
    var binary = event.target.result;
    var md5 = CryptoJS.MD5(binary).toString();
    console.log(md5);
  };

  reader.readAsBinaryString(file);
};

Я рекомендую добавить немного CSS, чтобы увидеть Drag & Зона падения:

#holder {
  border: 10px dashed #ccc;
  width: 300px;
  height: 300px;
}

#holder.hover {
  border: 10px dashed #333;
}

Подробнее о Drag & Функцию удаления можно найти здесь: File API & FileReader

Я протестировал образец в Google Chrome версии 32.

Ответ 4

Вам нужно использовать FileAPI. Он доступен в последних версиях FF и Chrome, но не в IE9. Захватите любую реализацию JS md5, предложенную выше. Я пробовал это и отказался от него, потому что JS был слишком медленным (минуты на больших файлах изображений). Можете пересмотреть его, если кто-то переписывает MD5 с помощью типизированных массивов.

Код выглядит примерно так:

HTML:     
<input type="file" id="file-dialog" multiple="true" accept="image/*">

JS (w JQuery)

$("#file-dialog").change(function() {
  handleFiles(this.files);
});

function handleFiles(files) {
    for (var i=0; i<files.length; i++) {
        var reader = new FileReader();
        reader.onload = function() {
        var md5 = binl_md5(reader.result, reader.result.length);
            console.log("MD5 is " + md5);
        };
        reader.onerror = function() {
            console.error("Could not read the file");
        };
        reader.readAsBinaryString(files.item(i));
     }
 }

Ответ 5

HTML5 + spark-md5 и Q

Предполагая, что вы используете современный браузер (который поддерживает HTML5 File API), вот как вы вычисляете хеш MD5 большого файла (он вычислит хеш для переменных чанков)

function calculateMD5Hash(file, bufferSize) {
  var def = Q.defer();

  var fileReader = new FileReader();
  var fileSlicer = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice;
  var hashAlgorithm = new SparkMD5();
  var totalParts = Math.ceil(file.size / bufferSize);
  var currentPart = 0;
  var startTime = new Date().getTime();

  fileReader.onload = function(e) {
    currentPart += 1;

    def.notify({
      currentPart: currentPart,
      totalParts: totalParts
    });

    var buffer = e.target.result;
    hashAlgorithm.appendBinary(buffer);

    if (currentPart < totalParts) {
      processNextPart();
      return;
    }

    def.resolve({
      hashResult: hashAlgorithm.end(),
      duration: new Date().getTime() - startTime
    });
  };

  fileReader.onerror = function(e) {
    def.reject(e);
  };

  function processNextPart() {
    var start = currentPart * bufferSize;
    var end = Math.min(start + bufferSize, file.size);
    fileReader.readAsBinaryString(fileSlicer.call(file, start, end));
  }

  processNextPart();
  return def.promise;
}

function calculate() {

  var input = document.getElementById('file');
  if (!input.files.length) {
    return;
  }

  var file = input.files[0];
  var bufferSize = Math.pow(1024, 2) * 10; // 10MB

  calculateMD5Hash(file, bufferSize).then(
    function(result) {
      // Success
      console.log(result);
    },
    function(err) {
      // There was an error,
    },
    function(progress) {
      // We get notified of the progress as it is executed
      console.log(progress.currentPart, 'of', progress.totalParts, 'Total bytes:', progress.currentPart * bufferSize, 'of', progress.totalParts * bufferSize);
    });
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/q.js/1.4.1/q.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/spark-md5/2.0.2/spark-md5.min.js"></script>

<div>
  <input type="file" id="file"/>
  <input type="button" onclick="calculate();" value="Calculate" class="btn primary" />
</div>

Ответ 6

Помимо невозможности получить доступ к файловой системе в JS, я бы не стал вообще доверять клиентская контрольная сумма. Так генерирование контрольной суммы на сервере является обязательным в любом случае. - Томалак 20 апреля 2009 года в 14:05

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

Ответ 7

Чтобы получить хэш файлов, есть много вариантов. Обычно проблема заключается в том, что очень медленно получать хэш больших файлов.

Я создал небольшую библиотеку, которая получает хэш файлов, с 64kb начала файла и 64kb его конца.

Пример в реальном времени: http://marcu87.github.com/hashme/ и библиотека: https://github.com/marcu87/hashme

Ответ 8

В Интернете есть несколько сценариев, чтобы создать хеш файл MD5.

Один из webtoolkit хорош, http://www.webtoolkit.info/javascript-md5.html

Хотя, я не думаю, что он будет иметь доступ к локальной файловой системе, поскольку этот доступ ограничен.

Ответ 9

С текущим HTML5 должно быть возможно рассчитать хэш файл md5 двоичного файла. Но я думаю, что шаг до этого был бы преобразовать банальные данные BlobBuilder в String, я пытаюсь сделать этот шаг: но не могу были успешными.

Вот код, который я пробовал: Преобразование BlobBuilder в строку, в HTML5 Javascript

Ответ 10

надеюсь, что вы нашли хорошее решение к настоящему времени. Если нет, то решение ниже - это реализация обещания ES6, основанная на js-spark-md5

import SparkMD5 from 'spark-md5';

// Read in chunks of 2MB
const CHUCK_SIZE = 2097152;

/**
 * Incrementally calculate checksum of a given file based on MD5 algorithm
 */
export const checksum = (file) =>
  new Promise((resolve, reject) => {
    let currentChunk = 0;
    const chunks = Math.ceil(file.size / CHUCK_SIZE);
    const blobSlice =
      File.prototype.slice ||
      File.prototype.mozSlice ||
      File.prototype.webkitSlice;
    const spark = new SparkMD5.ArrayBuffer();
    const fileReader = new FileReader();

    const loadNext = () => {
      const start = currentChunk * CHUCK_SIZE;
      const end =
        start + CHUCK_SIZE >= file.size ? file.size : start + CHUCK_SIZE;

      // Selectively read the file and only store part of it in memory.
      // This allows client-side applications to process huge files without the need for huge memory
      fileReader.readAsArrayBuffer(blobSlice.call(file, start, end));
    };

    fileReader.onload = e => {
      spark.append(e.target.result);
      currentChunk++;

      if (currentChunk < chunks) loadNext();
      else resolve(spark.end());
    };

    fileReader.onerror = () => {
      return reject('Calculating file checksum failed');
    };

    loadNext();
  });

Ответ 11

Я не верю, что в javascript есть способ доступа к содержимому загрузки файла. Поэтому вы не можете смотреть содержимое файла, чтобы генерировать сумму MD5.

Однако вы можете отправить файл на сервер, который затем может отправить сумму MD5 обратно или отправить содержимое файла обратно. Но это большая работа и, вероятно, не стоит для ваших целей.

Ответ 12

Ну его можно читать файлы с HTML5 File API (см. интерфейс Blob). Не проверено, но вы могли бы это сделать, возможно.

Ответ 13

Кроме того, вы никогда не должны доверять клиенту. Вам просто нужно будет переделать хэш после его загрузки.

Ответ 14

Без плагина вы не можете получить доступ к этим двоичным данным. Вы должны изучить использование Flash-приложения для загрузки. У меня есть коллеги, которые использовали SWFUpload, но я не знаю, как получить доступ к самому файлу. Возможно, вам придется изменить сам SWF, чтобы это разрешить.