This is the second article in the series “Untangling Reusable Code in Front-end Development.” The original title was different, but I changed it to make it more precise and clear. The experience here comes from the author’s work practice, into the front pit of the touch and roll.

background

In my work, I received a request to calculate the MD5 value of the file on the browser side, and then pass it to the backend storage when uploading the file. The old thinking is that the back end is just a couple of lines of code, such as md5_file in PHP.


      
  $filename = "file.jpg";
  $md5 = md5_file($filename);
  echo $md5;
? >
Copy the code

However, files are not uploaded to the back-end server, but directly to the OSS of Ali Cloud. If the back end requests files on oss for MD5 calculation, the server will be stressed. Therefore, the best way to calculate MD5 of files is to hand over the implementation to the client.

Although I have never had access to browser-based md5 computing files before, I used Spark-MD5 to solve this requirement after searching Google and Baidu. But if that were the end of the matter, there would have been no further thought of computing MD5 for network files, and this article would have emerged.

Then compute the local file MD5 requirement, received another requirement. The uploaded image needs to be compressed using the plupload function. The MD5 of the compressed image has been changed. After some time, I did not find a solution, and the technical director told me that the project would add new things later, so THAT I had better calculate MD5 when reviewing and uploading resources, so I began to explore the front-end calculation of NETWORK file MD5.

The File object

In Google, Baidu after a long time, did not find an accurate answer, including flash scheme. I think there are very few requirements or implementations to compute MD5 for network files on the browser side, and I have some guesses.

First, you should have a file and then calculate MD5 from the file, like this:

var file = new File(['www.domain.com/test.jpg'].'test.jpg', {type: 'image/jpg'});
Copy the code

The File object, however, does not take the URL argument to generate the File; here the URL is treated as a string, which is not the desired answer.

A Blob object

A Blob object is a file-like object. A File object inherits from a Blob object, and its usage is similar. A Blob cannot directly process a Blob object with a URL. To calculate md5, FileReader needs to read a File or Blob object and use Spark-MD5 to calculate MD5.

When XMLHttpRequest requests a file and specifies the responseType as blod, XMLHttpRequest returns a Blob object. If XMLHttpRequest specifies the responseType as blod, XMLHttpRequest returns a Blob object.

var request = new XMLHttpRequest();

request.open('GET', url, true);
request.responseType = 'blob';
request.onload = function() {
  // Similar Blob(3275) {size: 3275, type: "image/vnd.microsoft.icon"}
  console.log(request.response);
};
request.send();
Copy the code

At this point, the next step is to return MD5 (the official spark-MD5 example) by evaluating Blob objects with spark-MD5.

var request = new XMLHttpRequest();

request.open('GET', url, true);
request.responseType = 'blob';
request.onload = function() {
 var file = request.response;

var blobSlice = File.prototype.slice || File.prototype.mozSlice || 
    File.prototype.webkitSlice,
    chunkSize = 2097152.// Read in chunks of 2MB
    chunks = Math.ceil(file.size / chunkSize),
    currentChunk = 0,
    spark = new SparkMD5.ArrayBuffer(),
    fileReader = new FileReader();

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

    if (currentChunk < chunks) {
        loadNext();
    } else {
    	/ / get the md5
        var md5 = spark.end();
        console.log(md5); }}; fileReader.onerror =function () {
    console.error('File read failed');
};

function loadNext() {
    var start = currentChunk * chunkSize,
        end = ((start + chunkSize) >= file.size) ? file.size : start + chunkSize;

    fileReader.readAsArrayBuffer(blobSlice.call(file, start, end));
}

loadNext();
};
request.send();
Copy the code

Expand the spark – md5

Through the above code, it realizes the BROWSER side JS calculation network file MD5. According to the spark-MD5 usage mode, calculating the MD5 of the string is relatively simple:

SparkMD5.hash('hello world');//"5eb63bbbe01eeed093cb22bb8f5acdc3"
Copy the code

As shown above, only one line of code is needed, but it is slightly more complex when calculating files, and the code is not conducive to reuse. For the purpose of this series of articles on reusable code, and to include the ABILITY to compute MD5 for network files, a plug-in was packaged.


  • Github address: md5-util
  • Demo: MD5-util Demo, qr code attached below


Usage:

<script src="md5-util.min.js"></script>
Copy the code
// Calculates md5 for the local file
SparkMD5.file(file,function(md5){
 console.log(md5)
})

// Compute network file MD5
SparkMD5.file(url,function(md5){
 console.log(md5)
})
Copy the code

Browser-md5-file is referred to here. The difference is that this plug-in only extends spark-MD5 and adds the file method. All methods of spark-MD5 can be used in the plug-in.

Browser compatibility

This paper only discusses the compatibility of NETWORK file MD5. It has been tested many times in some mainstream browsers on PC and the MD5 obtained is correct. However, because the responseType of XMLHttpRequest is specified as BLOB, some compatibility problems are found on mobile terminals. It is known that bloB errors are returned in ios UC browser and Android 5.1.1 browser, resulting in md5 calculation errors.

Therefore, use it with caution when calculating THE MD5 of network files. If anyone has a better solution, please share.

Afterword.

For a long time, the task of calculating MD5 on the Web side is mainly assigned to the back end, but gradually the front-end technology can also be realized, which means that the front-end technology is gradually prosperous. However, “pain and happiness” is a good description of front-end development, using a new technology to complete the functions that could not be achieved before, but also faced with a variety of browser compatibility problems.

May we be inspired and move forward.


Related articles in this series (updated simultaneously) :

  1. Reorganize the reusable code in the front-end work (I) : make an integrated storage plug-in
  2. Reorganize reusable codes in front-end work (2) : Expand Spark-MD5 to support network file MD5 calculation