精华内容
下载资源
问答
  • 计算上传文件的MD5

    千次阅读 2017-07-12 12:48:25
    计算md5 function calculate(){ var fileReader = new FileReader(), box=document.getElementById('box'); blobSlice = File.prototype.mozSlice || File.prototype.webkitSlic
    <html>  
    <head>  
    <script type="text/javascript" src="http://localhost/spark-md5.js" ></script>  
    </head>  
      
    <body>  
    <input type="file" id="file" />  
    <div id="box"></div>  
    <button id="cal" type="button" οnclick="calculate()">计算md5</button>  
    </body>  
      
    <script type="text/javascript">  
    function calculate(){  
        var fileReader = new FileReader(),  
            box=document.getElementById('box');  
            blobSlice = File.prototype.mozSlice || File.prototype.webkitSlice || File.prototype.slice,  
            file = document.getElementById("file").files[0], 
    		//alert(file);
            chunkSize = 2097152,  
            // read in chunks of 2MB  
            chunks = Math.ceil(file.size / chunkSize),  
            currentChunk = 0,  
            spark = new SparkMD5();  
      
        fileReader.onload = function(e) {  
            console.log("read chunk nr", currentChunk + 1, "of", chunks);  
            spark.appendBinary(e.target.result); // append binary string  
            currentChunk++;  
      
            if (currentChunk < chunks) {  
                loadNext();  
            }  
            else {  
                console.log("finished loading");  
                box.innerText='MD5 hash:'+spark.end();  
                console.info("computed hash", spark.end()); // compute hash  
            }  
        };  
      
        function loadNext() {  
            var start = currentChunk * chunkSize,  
                end = start + chunkSize >= file.size ? file.size : start + chunkSize;  
      
            fileReader.readAsBinaryString(blobSlice.call(file, start, end));  
        };  
      
        loadNext();  
    }  
      
    </script>  
    </html>  

    插件:spark-md5.js

    (function (factory) {
        if (typeof exports === 'object') {
            // Node/CommonJS
            module.exports = factory();
        } else if (typeof define === 'function' && define.amd) {
            // AMD
            define(factory);
        } else {
            // Browser globals (with support for web workers)
            var glob;
    
            try {
                glob = window;
            } catch (e) {
                glob = self;
            }
    
            glob.SparkMD5 = factory();
        }
    }(function (undefined) {
    
        'use strict';
    
        /*
         * Fastest md5 implementation around (JKM md5).
         * Credits: Joseph Myers
         *
         * @see http://www.myersdaily.org/joseph/javascript/md5-text.html
         * @see http://jsperf.com/md5-shootout/7
         */
    
        /* this function is much faster,
          so if possible we use it. Some IEs
          are the only ones I know of that
          need the idiotic second function,
          generated by an if clause.  */
        var add32 = function (a, b) {
            return (a + b) & 0xFFFFFFFF;
        },
            hex_chr = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'];
    
    
        function cmn(q, a, b, x, s, t) {
            a = add32(add32(a, q), add32(x, t));
            return add32((a << s) | (a >>> (32 - s)), b);
        }
    
        function md5cycle(x, k) {
            var a = x[0],
                b = x[1],
                c = x[2],
                d = x[3];
    
            a += (b & c | ~b & d) + k[0] - 680876936 | 0;
            a  = (a << 7 | a >>> 25) + b | 0;
            d += (a & b | ~a & c) + k[1] - 389564586 | 0;
            d  = (d << 12 | d >>> 20) + a | 0;
            c += (d & a | ~d & b) + k[2] + 606105819 | 0;
            c  = (c << 17 | c >>> 15) + d | 0;
            b += (c & d | ~c & a) + k[3] - 1044525330 | 0;
            b  = (b << 22 | b >>> 10) + c | 0;
            a += (b & c | ~b & d) + k[4] - 176418897 | 0;
            a  = (a << 7 | a >>> 25) + b | 0;
            d += (a & b | ~a & c) + k[5] + 1200080426 | 0;
            d  = (d << 12 | d >>> 20) + a | 0;
            c += (d & a | ~d & b) + k[6] - 1473231341 | 0;
            c  = (c << 17 | c >>> 15) + d | 0;
            b += (c & d | ~c & a) + k[7] - 45705983 | 0;
            b  = (b << 22 | b >>> 10) + c | 0;
            a += (b & c | ~b & d) + k[8] + 1770035416 | 0;
            a  = (a << 7 | a >>> 25) + b | 0;
            d += (a & b | ~a & c) + k[9] - 1958414417 | 0;
            d  = (d << 12 | d >>> 20) + a | 0;
            c += (d & a | ~d & b) + k[10] - 42063 | 0;
            c  = (c << 17 | c >>> 15) + d | 0;
            b += (c & d | ~c & a) + k[11] - 1990404162 | 0;
            b  = (b << 22 | b >>> 10) + c | 0;
            a += (b & c | ~b & d) + k[12] + 1804603682 | 0;
            a  = (a << 7 | a >>> 25) + b | 0;
            d += (a & b | ~a & c) + k[13] - 40341101 | 0;
            d  = (d << 12 | d >>> 20) + a | 0;
            c += (d & a | ~d & b) + k[14] - 1502002290 | 0;
            c  = (c << 17 | c >>> 15) + d | 0;
            b += (c & d | ~c & a) + k[15] + 1236535329 | 0;
            b  = (b << 22 | b >>> 10) + c | 0;
    
            a += (b & d | c & ~d) + k[1] - 165796510 | 0;
            a  = (a << 5 | a >>> 27) + b | 0;
            d += (a & c | b & ~c) + k[6] - 1069501632 | 0;
            d  = (d << 9 | d >>> 23) + a | 0;
            c += (d & b | a & ~b) + k[11] + 643717713 | 0;
            c  = (c << 14 | c >>> 18) + d | 0;
            b += (c & a | d & ~a) + k[0] - 373897302 | 0;
            b  = (b << 20 | b >>> 12) + c | 0;
            a += (b & d | c & ~d) + k[5] - 701558691 | 0;
            a  = (a << 5 | a >>> 27) + b | 0;
            d += (a & c | b & ~c) + k[10] + 38016083 | 0;
            d  = (d << 9 | d >>> 23) + a | 0;
            c += (d & b | a & ~b) + k[15] - 660478335 | 0;
            c  = (c << 14 | c >>> 18) + d | 0;
            b += (c & a | d & ~a) + k[4] - 405537848 | 0;
            b  = (b << 20 | b >>> 12) + c | 0;
            a += (b & d | c & ~d) + k[9] + 568446438 | 0;
            a  = (a << 5 | a >>> 27) + b | 0;
            d += (a & c | b & ~c) + k[14] - 1019803690 | 0;
            d  = (d << 9 | d >>> 23) + a | 0;
            c += (d & b | a & ~b) + k[3] - 187363961 | 0;
            c  = (c << 14 | c >>> 18) + d | 0;
            b += (c & a | d & ~a) + k[8] + 1163531501 | 0;
            b  = (b << 20 | b >>> 12) + c | 0;
            a += (b & d | c & ~d) + k[13] - 1444681467 | 0;
            a  = (a << 5 | a >>> 27) + b | 0;
            d += (a & c | b & ~c) + k[2] - 51403784 | 0;
            d  = (d << 9 | d >>> 23) + a | 0;
            c += (d & b | a & ~b) + k[7] + 1735328473 | 0;
            c  = (c << 14 | c >>> 18) + d | 0;
            b += (c & a | d & ~a) + k[12] - 1926607734 | 0;
            b  = (b << 20 | b >>> 12) + c | 0;
    
            a += (b ^ c ^ d) + k[5] - 378558 | 0;
            a  = (a << 4 | a >>> 28) + b | 0;
            d += (a ^ b ^ c) + k[8] - 2022574463 | 0;
            d  = (d << 11 | d >>> 21) + a | 0;
            c += (d ^ a ^ b) + k[11] + 1839030562 | 0;
            c  = (c << 16 | c >>> 16) + d | 0;
            b += (c ^ d ^ a) + k[14] - 35309556 | 0;
            b  = (b << 23 | b >>> 9) + c | 0;
            a += (b ^ c ^ d) + k[1] - 1530992060 | 0;
            a  = (a << 4 | a >>> 28) + b | 0;
            d += (a ^ b ^ c) + k[4] + 1272893353 | 0;
            d  = (d << 11 | d >>> 21) + a | 0;
            c += (d ^ a ^ b) + k[7] - 155497632 | 0;
            c  = (c << 16 | c >>> 16) + d | 0;
            b += (c ^ d ^ a) + k[10] - 1094730640 | 0;
            b  = (b << 23 | b >>> 9) + c | 0;
            a += (b ^ c ^ d) + k[13] + 681279174 | 0;
            a  = (a << 4 | a >>> 28) + b | 0;
            d += (a ^ b ^ c) + k[0] - 358537222 | 0;
            d  = (d << 11 | d >>> 21) + a | 0;
            c += (d ^ a ^ b) + k[3] - 722521979 | 0;
            c  = (c << 16 | c >>> 16) + d | 0;
            b += (c ^ d ^ a) + k[6] + 76029189 | 0;
            b  = (b << 23 | b >>> 9) + c | 0;
            a += (b ^ c ^ d) + k[9] - 640364487 | 0;
            a  = (a << 4 | a >>> 28) + b | 0;
            d += (a ^ b ^ c) + k[12] - 421815835 | 0;
            d  = (d << 11 | d >>> 21) + a | 0;
            c += (d ^ a ^ b) + k[15] + 530742520 | 0;
            c  = (c << 16 | c >>> 16) + d | 0;
            b += (c ^ d ^ a) + k[2] - 995338651 | 0;
            b  = (b << 23 | b >>> 9) + c | 0;
    
            a += (c ^ (b | ~d)) + k[0] - 198630844 | 0;
            a  = (a << 6 | a >>> 26) + b | 0;
            d += (b ^ (a | ~c)) + k[7] + 1126891415 | 0;
            d  = (d << 10 | d >>> 22) + a | 0;
            c += (a ^ (d | ~b)) + k[14] - 1416354905 | 0;
            c  = (c << 15 | c >>> 17) + d | 0;
            b += (d ^ (c | ~a)) + k[5] - 57434055 | 0;
            b  = (b << 21 |b >>> 11) + c | 0;
            a += (c ^ (b | ~d)) + k[12] + 1700485571 | 0;
            a  = (a << 6 | a >>> 26) + b | 0;
            d += (b ^ (a | ~c)) + k[3] - 1894986606 | 0;
            d  = (d << 10 | d >>> 22) + a | 0;
            c += (a ^ (d | ~b)) + k[10] - 1051523 | 0;
            c  = (c << 15 | c >>> 17) + d | 0;
            b += (d ^ (c | ~a)) + k[1] - 2054922799 | 0;
            b  = (b << 21 |b >>> 11) + c | 0;
            a += (c ^ (b | ~d)) + k[8] + 1873313359 | 0;
            a  = (a << 6 | a >>> 26) + b | 0;
            d += (b ^ (a | ~c)) + k[15] - 30611744 | 0;
            d  = (d << 10 | d >>> 22) + a | 0;
            c += (a ^ (d | ~b)) + k[6] - 1560198380 | 0;
            c  = (c << 15 | c >>> 17) + d | 0;
            b += (d ^ (c | ~a)) + k[13] + 1309151649 | 0;
            b  = (b << 21 |b >>> 11) + c | 0;
            a += (c ^ (b | ~d)) + k[4] - 145523070 | 0;
            a  = (a << 6 | a >>> 26) + b | 0;
            d += (b ^ (a | ~c)) + k[11] - 1120210379 | 0;
            d  = (d << 10 | d >>> 22) + a | 0;
            c += (a ^ (d | ~b)) + k[2] + 718787259 | 0;
            c  = (c << 15 | c >>> 17) + d | 0;
            b += (d ^ (c | ~a)) + k[9] - 343485551 | 0;
            b  = (b << 21 | b >>> 11) + c | 0;
    
            x[0] = a + x[0] | 0;
            x[1] = b + x[1] | 0;
            x[2] = c + x[2] | 0;
            x[3] = d + x[3] | 0;
        }
    
        function md5blk(s) {
            var md5blks = [],
                i; /* Andy King said do it this way. */
    
            for (i = 0; i < 64; i += 4) {
                md5blks[i >> 2] = s.charCodeAt(i) + (s.charCodeAt(i + 1) << 8) + (s.charCodeAt(i + 2) << 16) + (s.charCodeAt(i + 3) << 24);
            }
            return md5blks;
        }
    
        function md5blk_array(a) {
            var md5blks = [],
                i; /* Andy King said do it this way. */
    
            for (i = 0; i < 64; i += 4) {
                md5blks[i >> 2] = a[i] + (a[i + 1] << 8) + (a[i + 2] << 16) + (a[i + 3] << 24);
            }
            return md5blks;
        }
    
        function md51(s) {
            var n = s.length,
                state = [1732584193, -271733879, -1732584194, 271733878],
                i,
                length,
                tail,
                tmp,
                lo,
                hi;
    
            for (i = 64; i <= n; i += 64) {
                md5cycle(state, md5blk(s.substring(i - 64, i)));
            }
            s = s.substring(i - 64);
            length = s.length;
            tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
            for (i = 0; i < length; i += 1) {
                tail[i >> 2] |= s.charCodeAt(i) << ((i % 4) << 3);
            }
            tail[i >> 2] |= 0x80 << ((i % 4) << 3);
            if (i > 55) {
                md5cycle(state, tail);
                for (i = 0; i < 16; i += 1) {
                    tail[i] = 0;
                }
            }
    
            // Beware that the final length might not fit in 32 bits so we take care of that
            tmp = n * 8;
            tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/);
            lo = parseInt(tmp[2], 16);
            hi = parseInt(tmp[1], 16) || 0;
    
            tail[14] = lo;
            tail[15] = hi;
    
            md5cycle(state, tail);
            return state;
        }
    
        function md51_array(a) {
            var n = a.length,
                state = [1732584193, -271733879, -1732584194, 271733878],
                i,
                length,
                tail,
                tmp,
                lo,
                hi;
    
            for (i = 64; i <= n; i += 64) {
                md5cycle(state, md5blk_array(a.subarray(i - 64, i)));
            }
    
            // Not sure if it is a bug, however IE10 will always produce a sub array of length 1
            // containing the last element of the parent array if the sub array specified starts
            // beyond the length of the parent array - weird.
            // https://connect.microsoft.com/IE/feedback/details/771452/typed-array-subarray-issue
            a = (i - 64) < n ? a.subarray(i - 64) : new Uint8Array(0);
    
            length = a.length;
            tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
            for (i = 0; i < length; i += 1) {
                tail[i >> 2] |= a[i] << ((i % 4) << 3);
            }
    
            tail[i >> 2] |= 0x80 << ((i % 4) << 3);
            if (i > 55) {
                md5cycle(state, tail);
                for (i = 0; i < 16; i += 1) {
                    tail[i] = 0;
                }
            }
    
            // Beware that the final length might not fit in 32 bits so we take care of that
            tmp = n * 8;
            tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/);
            lo = parseInt(tmp[2], 16);
            hi = parseInt(tmp[1], 16) || 0;
    
            tail[14] = lo;
            tail[15] = hi;
    
            md5cycle(state, tail);
    
            return state;
        }
    
        function rhex(n) {
            var s = '',
                j;
            for (j = 0; j < 4; j += 1) {
                s += hex_chr[(n >> (j * 8 + 4)) & 0x0F] + hex_chr[(n >> (j * 8)) & 0x0F];
            }
            return s;
        }
    
        function hex(x) {
            var i;
            for (i = 0; i < x.length; i += 1) {
                x[i] = rhex(x[i]);
            }
            return x.join('');
        }
    
        // In some cases the fast add32 function cannot be used..
        if (hex(md51('hello')) !== '5d41402abc4b2a76b9719d911017c592') {
            add32 = function (x, y) {
                var lsw = (x & 0xFFFF) + (y & 0xFFFF),
                    msw = (x >> 16) + (y >> 16) + (lsw >> 16);
                return (msw << 16) | (lsw & 0xFFFF);
            };
        }
    
        // ---------------------------------------------------
    
        /**
         * ArrayBuffer slice polyfill.
         *
         * @see https://github.com/ttaubert/node-arraybuffer-slice
         */
    
        if (typeof ArrayBuffer !== 'undefined' && !ArrayBuffer.prototype.slice) {
            (function () {
                function clamp(val, length) {
                    val = (val | 0) || 0;
    
                    if (val < 0) {
                        return Math.max(val + length, 0);
                    }
    
                    return Math.min(val, length);
                }
    
                ArrayBuffer.prototype.slice = function (from, to) {
                    var length = this.byteLength,
                        begin = clamp(from, length),
                        end = length,
                        num,
                        target,
                        targetArray,
                        sourceArray;
    
                    if (to !== undefined) {
                        end = clamp(to, length);
                    }
    
                    if (begin > end) {
                        return new ArrayBuffer(0);
                    }
    
                    num = end - begin;
                    target = new ArrayBuffer(num);
                    targetArray = new Uint8Array(target);
    
                    sourceArray = new Uint8Array(this, begin, num);
                    targetArray.set(sourceArray);
    
                    return target;
                };
            })();
        }
    
        // ---------------------------------------------------
    
        /**
         * Helpers.
         */
    
        function toUtf8(str) {
            if (/[\u0080-\uFFFF]/.test(str)) {
                str = unescape(encodeURIComponent(str));
            }
    
            return str;
        }
    
        function utf8Str2ArrayBuffer(str, returnUInt8Array) {
            var length = str.length,
               buff = new ArrayBuffer(length),
               arr = new Uint8Array(buff),
               i;
    
            for (i = 0; i < length; i += 1) {
                arr[i] = str.charCodeAt(i);
            }
    
            return returnUInt8Array ? arr : buff;
        }
    
        function arrayBuffer2Utf8Str(buff) {
            return String.fromCharCode.apply(null, new Uint8Array(buff));
        }
    
        function concatenateArrayBuffers(first, second, returnUInt8Array) {
            var result = new Uint8Array(first.byteLength + second.byteLength);
    
            result.set(new Uint8Array(first));
            result.set(new Uint8Array(second), first.byteLength);
    
            return returnUInt8Array ? result : result.buffer;
        }
    
        function hexToBinaryString(hex) {
            var bytes = [],
                length = hex.length,
                x;
    
            for (x = 0; x < length - 1; x += 2) {
                bytes.push(parseInt(hex.substr(x, 2), 16));
            }
    
            return String.fromCharCode.apply(String, bytes);
        }
    
        // ---------------------------------------------------
    
        /**
         * SparkMD5 OOP implementation.
         *
         * Use this class to perform an incremental md5, otherwise use the
         * static methods instead.
         */
    
        function SparkMD5() {
            // call reset to init the instance
            this.reset();
        }
    
        /**
         * Appends a string.
         * A conversion will be applied if an utf8 string is detected.
         *
         * @param {String} str The string to be appended
         *
         * @return {SparkMD5} The instance itself
         */
        SparkMD5.prototype.append = function (str) {
            // Converts the string to utf8 bytes if necessary
            // Then append as binary
            this.appendBinary(toUtf8(str));
    
            return this;
        };
    
        /**
         * Appends a binary string.
         *
         * @param {String} contents The binary string to be appended
         *
         * @return {SparkMD5} The instance itself
         */
        SparkMD5.prototype.appendBinary = function (contents) {
            this._buff += contents;
            this._length += contents.length;
    
            var length = this._buff.length,
                i;
    
            for (i = 64; i <= length; i += 64) {
                md5cycle(this._hash, md5blk(this._buff.substring(i - 64, i)));
            }
    
            this._buff = this._buff.substring(i - 64);
    
            return this;
        };
    
        /**
         * Finishes the incremental computation, reseting the internal state and
         * returning the result.
         *
         * @param {Boolean} raw True to get the raw string, false to get the hex string
         *
         * @return {String} The result
         */
        SparkMD5.prototype.end = function (raw) {
            var buff = this._buff,
                length = buff.length,
                i,
                tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
                ret;
    
            for (i = 0; i < length; i += 1) {
                tail[i >> 2] |= buff.charCodeAt(i) << ((i % 4) << 3);
            }
    
            this._finish(tail, length);
            ret = hex(this._hash);
    
            if (raw) {
                ret = hexToBinaryString(ret);
            }
    
            this.reset();
    
            return ret;
        };
    
        /**
         * Resets the internal state of the computation.
         *
         * @return {SparkMD5} The instance itself
         */
        SparkMD5.prototype.reset = function () {
            this._buff = '';
            this._length = 0;
            this._hash = [1732584193, -271733879, -1732584194, 271733878];
    
            return this;
        };
    
        /**
         * Gets the internal state of the computation.
         *
         * @return {Object} The state
         */
        SparkMD5.prototype.getState = function () {
            return {
                buff: this._buff,
                length: this._length,
                hash: this._hash
            };
        };
    
        /**
         * Gets the internal state of the computation.
         *
         * @param {Object} state The state
         *
         * @return {SparkMD5} The instance itself
         */
        SparkMD5.prototype.setState = function (state) {
            this._buff = state.buff;
            this._length = state.length;
            this._hash = state.hash;
    
            return this;
        };
    
        /**
         * Releases memory used by the incremental buffer and other additional
         * resources. If you plan to use the instance again, use reset instead.
         */
        SparkMD5.prototype.destroy = function () {
            delete this._hash;
            delete this._buff;
            delete this._length;
        };
    
        /**
         * Finish the final calculation based on the tail.
         *
         * @param {Array}  tail   The tail (will be modified)
         * @param {Number} length The length of the remaining buffer
         */
        SparkMD5.prototype._finish = function (tail, length) {
            var i = length,
                tmp,
                lo,
                hi;
    
            tail[i >> 2] |= 0x80 << ((i % 4) << 3);
            if (i > 55) {
                md5cycle(this._hash, tail);
                for (i = 0; i < 16; i += 1) {
                    tail[i] = 0;
                }
            }
    
            // Do the final computation based on the tail and length
            // Beware that the final length may not fit in 32 bits so we take care of that
            tmp = this._length * 8;
            tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/);
            lo = parseInt(tmp[2], 16);
            hi = parseInt(tmp[1], 16) || 0;
    
            tail[14] = lo;
            tail[15] = hi;
            md5cycle(this._hash, tail);
        };
    
        /**
         * Performs the md5 hash on a string.
         * A conversion will be applied if utf8 string is detected.
         *
         * @param {String}  str The string
         * @param {Boolean} [raw] True to get the raw string, false to get the hex string
         *
         * @return {String} The result
         */
        SparkMD5.hash = function (str, raw) {
            // Converts the string to utf8 bytes if necessary
            // Then compute it using the binary function
            return SparkMD5.hashBinary(toUtf8(str), raw);
        };
    
        /**
         * Performs the md5 hash on a binary string.
         *
         * @param {String}  content The binary string
         * @param {Boolean} [raw]     True to get the raw string, false to get the hex string
         *
         * @return {String} The result
         */
        SparkMD5.hashBinary = function (content, raw) {
            var hash = md51(content),
                ret = hex(hash);
    
            return raw ? hexToBinaryString(ret) : ret;
        };
    
        // ---------------------------------------------------
    
        /**
         * SparkMD5 OOP implementation for array buffers.
         *
         * Use this class to perform an incremental md5 ONLY for array buffers.
         */
        SparkMD5.ArrayBuffer = function () {
            // call reset to init the instance
            this.reset();
        };
    
        /**
         * Appends an array buffer.
         *
         * @param {ArrayBuffer} arr The array to be appended
         *
         * @return {SparkMD5.ArrayBuffer} The instance itself
         */
        SparkMD5.ArrayBuffer.prototype.append = function (arr) {
            var buff = concatenateArrayBuffers(this._buff.buffer, arr, true),
                length = buff.length,
                i;
    
            this._length += arr.byteLength;
    
            for (i = 64; i <= length; i += 64) {
                md5cycle(this._hash, md5blk_array(buff.subarray(i - 64, i)));
            }
    
            this._buff = (i - 64) < length ? new Uint8Array(buff.buffer.slice(i - 64)) : new Uint8Array(0);
    
            return this;
        };
    
        /**
         * Finishes the incremental computation, reseting the internal state and
         * returning the result.
         *
         * @param {Boolean} raw True to get the raw string, false to get the hex string
         *
         * @return {String} The result
         */
        SparkMD5.ArrayBuffer.prototype.end = function (raw) {
            var buff = this._buff,
                length = buff.length,
                tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
                i,
                ret;
    
            for (i = 0; i < length; i += 1) {
                tail[i >> 2] |= buff[i] << ((i % 4) << 3);
            }
    
            this._finish(tail, length);
            ret = hex(this._hash);
    
            if (raw) {
                ret = hexToBinaryString(ret);
            }
    
            this.reset();
    
            return ret;
        };
    
        /**
         * Resets the internal state of the computation.
         *
         * @return {SparkMD5.ArrayBuffer} The instance itself
         */
        SparkMD5.ArrayBuffer.prototype.reset = function () {
            this._buff = new Uint8Array(0);
            this._length = 0;
            this._hash = [1732584193, -271733879, -1732584194, 271733878];
    
            return this;
        };
    
        /**
         * Gets the internal state of the computation.
         *
         * @return {Object} The state
         */
        SparkMD5.ArrayBuffer.prototype.getState = function () {
            var state = SparkMD5.prototype.getState.call(this);
    
            // Convert buffer to a string
            state.buff = arrayBuffer2Utf8Str(state.buff);
    
            return state;
        };
    
        /**
         * Gets the internal state of the computation.
         *
         * @param {Object} state The state
         *
         * @return {SparkMD5.ArrayBuffer} The instance itself
         */
        SparkMD5.ArrayBuffer.prototype.setState = function (state) {
            // Convert string to buffer
            state.buff = utf8Str2ArrayBuffer(state.buff, true);
    
            return SparkMD5.prototype.setState.call(this, state);
        };
    
        SparkMD5.ArrayBuffer.prototype.destroy = SparkMD5.prototype.destroy;
    
        SparkMD5.ArrayBuffer.prototype._finish = SparkMD5.prototype._finish;
    
        /**
         * Performs the md5 hash on an array buffer.
         *
         * @param {ArrayBuffer} arr The array buffer
         * @param {Boolean}     [raw] True to get the raw string, false to get the hex one
         *
         * @return {String} The result
         */
        SparkMD5.ArrayBuffer.hash = function (arr, raw) {
            var hash = md51_array(new Uint8Array(arr)),
                ret = hex(hash);
    
            return raw ? hexToBinaryString(ret) : ret;
        };
    
        return SparkMD5;
    }));
    



    展开全文
  • 在系统的开发过程中,经常会有上传大容量视频的需求,而大容量视频的上传则会花费很长时间,在一定程度上需要用户等待很久,用户体验不佳,为此有开发秒传功能的需要,本文章实现秒传的原理是在执行上传之前先检查...

    1、应用场景和实现原理

    在系统的开发过程中,经常会有上传大容量视频的需求,而大容量视频的上传则会花费很长时间,在一定程度上需要用户等待很久,用户体验不佳,为此有开发秒传功能的需要,本文章实现秒传的原理是在执行上传之前先检查之前是否已经上传过,若上传过则不再重复上传,直接返回该视频存放在服务器的URL,若没有上传过则进行上传。

    那么如何判断该视频是否已经上传过是本文章的重点,采取的是通过文件的MD5进行判断(同一视频文件的MD5值是相同的)

    2、代码实现

    readFileMD5 = (file) => {
        // 读取视频文件的md5
        console.log("获取文件的MD5值")
        let fileRederInstance = new FileReader()
        fileRederInstance.readAsBinaryString(file)
        fileRederInstance.addEventListener('load', e => {
          let fileBolb = e.target.result
          fileMD5 = md5(fileBolb)
         //是否已经上传的网络请求
          uploadCheckAxios({ "md5": fileMD5 }).then(res => {
            if (res.data.code == 0) {
              console.log("文件已被上传")
            }
            else { 
              console.log("文件未被上传,将分片上传")
            }
          }).catch((e) => {
            console.log(e)
          })
        })
      }

     

    展开全文
  • 5个目标文件,演示Address EJB的实现 ,创建一个EJB测试客户端,得到名字上下文,查询jndi名,通过强制转型得到Home接口,getInitialContext()函数返回一个经过初始化的上下文,用client的getHome()函数调用Home接口...
  • $(".upRemind").html("等待上传..."); $(".percent").html("0%"); $(".progress2").show(); $(".progress-bar2").width(0); upLast=upStart=upEnd=lastStart=lastEnd=everyLoad=0; lastFlag=1; everyAddNum=3...

    此功能也是耗费了大致2周的时间,开发阶段遇到了不少问题.参与这个功能的实现主要包括前端1名以及本人.

    当然我们技术部门老大(经理)负责引导和提供开发中遇到的问题思路.


    大致实现逻辑我在这里做一个简单的总结(本人语言组织能力不足,阅读时遇到问题和疑问,谢谢指出):

    环境要求:

    1.apache/nginx作为服务器.

    2.PHP环境(v5.6及以上).

    3.浏览器(谷歌/火狐).


    实现思路:

    1.将用户选择的文件进行按照固定大小进行分片(每一片的字节尽量的小).

    2.使用循环每次发送定量的请求,附带当前分片的MD5密文以及编号(请求之间不等待相互的响应,发送的http请求数取决客户端浏览器内核和系统是32位还是64位).

    3.后端(PHP)负责接收每次的数据并保存一个临时的文件.(每次请求对当前的片进行验证,失败返回,前端收到请求的状态再一次的发送当前请求)

    4.最终将缓存的文件进行合并.(这次也需要验证,失败返回,重新上传).


    代码:

    =================javascript代码部分======================

    <!doctype html>
    <html>
    <head>
    <title>浏览器上传100MB文件,MD5验证,分片上传</title>
    </head>
    <body>
    <div class="uploadMusic">
        <span>选择文件</span>
        <input type="file" id="upMusic" accept=".wav" />
    </div>
    <div class="uploadStart">
        <div class="progress2">
            <div class="progress-bar2">
                <div class="percent"></div>
                <a class="upload-close" href="javascript:void(0)" id="uploadClose">x</a>
            </div>
        </div>
        <div class="upRemind"></div>
    </div>
    <div style="top: 20px;" class="relative">
        <p id="upload_audio_html">请上传<B>20M</B>以上<B>WAV</B>格式的音乐文件</p>
        <input id="file_path" type="hidden" />
    </div>
    <script src="jquery-1.11.1.min.js"></script>
    <script src="md5.js"></script>
    <script type="application/javascript">
        $(function(){
            var preUploadSize = 1024*128;   //每次上传文件的一段,单位:字节
            var upLast=upStart=upEnd=lastStart=lastEnd=0;
            var percent=0;
            var lastFlag=1;
            var upNum,file,upNum1;//upNum每次还剩余的上传次数   upNum1总共需要上传的次数,用来获取最后一次
            var fixNum=3;      //固定的循环次数
            var uuid;          //改变文件时生成的uuid码
            var everyAddNum=3; //每次加3用来判断成功了几次
            var everyLoad=0;   //记录每次加载
            var fileAllMd5;
            var onceTime=0;
            var savePath;
            var alertFlag=false;
            var networkFlag=false;
            var fileName;
            var closeFlag=true;
            $("#uploadClose").on("click",function(){
                closeFlag=false;
                $('#upMusic')[0].disabled=false;
                $(".uploadMusic span").removeClass("file-disable");
                fileAllMd5=null;
                $('#upMusic').val("");
            })
            $('#upMusic').change(function() {
                if(this.files){
                    if(onceTime<5){ //上传次数限制
                        $('#upMusic')[0].disabled=true;
                        $(".uploadMusic span").addClass("file-disable");
                        closeFlag=true;
                        var files = this.files;
                        file = files[0];
                        if(file.name){
                            fileName=file.name;
                            var arr = [];
                            var hexDigits = "0123456789abcdef";
                            for (var i = 0; i < 36; i++) {
                                arr[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
                            }
                            arr[14] = "4";
                            arr[19] = hexDigits.substr((arr[19] & 0x3) | 0x8, 1);
                            uuid = arr.join("");
                            $(".upRemind").html("等待上传...");
                            $(".percent").html("0%");
                            $(".progress2").show();
                            $(".progress-bar2").width(0);
                            upLast=upStart=upEnd=lastStart=lastEnd=everyLoad=0;
                            lastFlag=1;
                            everyAddNum=3;
                            alertFlag=false;
                            networkFlag=false;
                            fileAllMd5=null;
                            var f=new FileReader();
                            f.readAsBinaryString(file);
                            $(f).load(function(e){
                                fileAllMd5=e.target.result;
                                fileAllMd5=hex_md5(fileAllMd5);
                            })
                            var size = file.size;
                            upNum=upNum1=Math.ceil(size/preUploadSize);  //21   4.1
                            start(upNum,uuid);
                        }else{
                            alert("您的上传次数过多,如有任何问题请与运营人员联系。");
                            return false;
                        }
                        onceTime++;
                    }
                }else{
                    alert("为获得最佳上传体验,我们推荐您使用最新版Chrome、火狐或360极速浏览器。");
                }
            })
            function start(upNum,uuid){
                if(closeFlag){
                    if(upNum>fixNum){
                        for(i=0;i<fixNum;i++){
                            upStart=upEnd;
                            upEnd = upStart + preUploadSize;
                            everyLoad++;   //3 6
                            upload(file,everyLoad,lastFlag,upStart,upEnd,uuid);
                        }
                    }else{
                        for(i=0;i<upNum;i++){
                            upStart=upEnd;
                            upEnd = upStart + preUploadSize;
                            everyLoad++;   //7 8
                            if(everyLoad==upNum1){
                                lastStart = upStart;
                                lastEnd = upEnd;
                                // upload(file,upNum1,flag,lastStart,lastEnd,uuid);
                            }else{
                                upload(file,everyLoad,lastFlag,upStart,upEnd,uuid);
                            }
                        }
                    }
                }else{
                    $(".upRemind").html("");
                    $(".progress2").hide();
                    return false;
                }
            }
            var again=function(data){
                var uploadMusicUrl=$("#uploadMusicUrl").val();
                $.ajax({
                    type: 'POST',
                    url: uploadMusicUrl,
                    data: data,
                    timeout : 60000, //超时时间设置30秒请求
                    contentType: false,
                    // 避开jQuery对 data 对象的默认处理
                    processData: false,
                    crossDomain:true,
                    success:function(msg){
                        var msg=$.parseJSON(msg);
                        if(msg.state){
                            upLast++;
                            showprogress(upLast*preUploadSize);
                            if(upLast==everyAddNum){
                                upNum-=fixNum;
                                if(upNum>fixNum){
                                    everyAddNum+=3;
                                    start(upNum,uuid);
                                }else{
                                    upNum=upNum;
                                    start(upNum,uuid);
                                }
                            }
                            if(upLast==upNum1-1){
                                lastFlag=2;
                                upload(file,upNum1,lastFlag,lastStart,lastEnd,uuid);
                            }
                            savePath=msg.savePath;
                            $('#file_path').val(msg.savePath);
                        }else{
                            if(msg.errorState=="fragmentFail"){
                                upLast--;
                                upload(file,msg.n,msg.start,msg.end,uuid);
                            }else if(msg.errorState!="methodFail"){
                                if(!alertFlag){
                                    alertFlag=true;
                                    alert(""+msg.msg+",请重新上传");
                                }
                                $(".progress2").hide();
                                $(".upRemind").html("");
                                $('#upMusic')[0].disabled=false;
                                $(".uploadMusic span").removeClass("file-disable");
                                return false;
                            }
                        }
                    },
                    error: function (jqXHR, textStatus, errorThrown) {
                        if(jqXHR.statusText == 'timeout' || textStatus == 'timeout' || errorThrown == 'timeout')
                        {
                            if(!networkFlag){
                                networkFlag=true;
                                alert("您当前的网络不佳,请稍后再试");
                            }
                            $(".upRemind").html("上传失败").css("color","#f00");
                            $(".progress2").hide();
                            return false;
                        }
    
                    }
                })
            }
            function upload(file,i,lastFlag,start,end,uuid) {
                var data = new FormData();
                var part=file.slice(start,end);
                var r=new FileReader();
                r.readAsBinaryString(part);
                $(r).load(function(e){
                    if(lastFlag==2){
                        //fileAllMd5=hex_md5(file);
                        data.append("fileAllMd5",fileAllMd5);
                    }
                    var bolb=e.target.result;
                    var b=hex_md5(bolb);
                    data.append("name", encodeURIComponent(file.name));
                    data.append("n",i);
                    data.append("file", file.slice(start, end));
                    data.append("md5",b);
                    data.append("flag",lastFlag);
                    data.append("start",start);
                    data.append("end",end);
                    data.append("uuid",uuid);
                    data.append('mirotime',new Date().getTime());
                    again(data);
                })
            }
    
            function showprogress(per) {
                if(per<file.size){
                    percent=(per/file.size)*100;
                    $(".upRemind").html("上传中");
                }else{
                    percent=100;
                    $(".upRemind").html(""+fileName+"上传完成");
                    $('.progress2').hide();
                    $('#upMusic')[0].disabled=false;
                    $(".uploadMusic span").removeClass("file-disable");
                }
                //console.log(percent);
                $('.progress-bar2').width(percent+ '%');
                $(".percent").html(Math.ceil(percent)+ '%');
            }
        })
    </script>
    </body>
    </html>




    ===================php代码部分========================

    <?php
    date_default_timezone_set('PRC');
    error_reporting(E_ALL & ~E_NOTICE);
    $state = ['state' => false];
    
    $state['errorState'] = 'methodFail';//传输方式
    if(empty($_POST)):
        $state['msg'] = '上传方式仅限POST提交';
        $state['msgInfo'] = '传输的方法有误,仅限POST方式提交';
        echo json_encode($state);
        exit;
    endif;
    $oldFileName =  $_POST['name'] ? urldecode(trim($_POST['name'])) : null; //原始文件名
    $md5Name = md5(substr($oldFileName,strpos($oldFileName,'.wav'))).'.wav'; //文件名
    $uid = isset($_POST['uid']) ? (int)$_POST['uid'] : null; //uid
    $uuid = isset($_POST['uuid']) ? htmlspecialchars(trim($_POST['uuid'])) : null; //唯一的uuid
    $md5 = isset($_POST['md5']) ? htmlspecialchars(trim($_POST['md5'])) : null; //文件加密的字符串
    $fileAllMd5 = isset($_POST['fileAllMd5']) ? htmlspecialchars(trim($_POST['fileAllMd5'])) : null; //整体文件加密的字符串
    $flag = is_numeric($_POST['flag']) ? (int)$_POST['flag'] : null;//1 不是最后一次传输 2是最后一次传输
    $n = is_numeric($_POST['n']) ? (int)$_POST['n'] : null;
    $start = is_numeric($_POST['start']) ? (int)$_POST['start'] : null; //起始的位置
    $end = is_numeric($_POST['end']) ? (int)$_POST['end'] : null; //截止的位置
    
    
    $state['errorState'] = 'paramsFail';//起始的错误代号
    $state['msg'] = '传输的参数有误';
    if(!is_numeric($start) || !is_numeric($end) || !is_numeric($n) ):
        $state['msgInfo'] = '传输的参数start或end或n必须是数字';
        echo json_encode($state);
        exit;
    endif;
    if($flag != 1 && $flag != 2):
        $state['msgInfo'] = '参数有误flag必须是1或2';
        echo json_encode($state);
        exit;
    endif;
    if($md5 === null || $oldFileName === null || $uuid === null):
        $state['msgInfo'] = '缺少必须的参数md5或文件名或uuid';
        echo json_encode($state);
        exit;
    endif;
    if(strpos($md5,'.') !== false):
        $state['msgInfo'] = '参数有误,md5校验码传输不符合要求';
        echo json_encode($state);
        exit;
    endif;
    if(strpos($uuid,'.')):
        $state['msgInfo'] = '参数有误,uuid传输有误';
        echo json_encode($state);
        exit;
    endif;
    
    $path_parts = pathinfo($oldFileName);
    $ext = strtolower($path_parts['extension']);
    $extArray = ['wav'];
    if(!in_array($ext,$extArray)):
        $state['msgInfo'] = '文件后缀必须是.wav文件';
        echo json_encode($state);
        exit;
    endif;
    
    $state['errorState'] = 'fileUploadFail';//文件上传出错
    $state['msg'] = '文件上传出错';
    switch ($_FILES['file']['error']):
        case UPLOAD_ERR_OK:
            $msgInfo = '';
            break;
        case UPLOAD_ERR_INI_SIZE:
        case UPLOAD_ERR_FORM_SIZE:
            $msgInfo = "上传文件超出限制";
            break;
        case UPLOAD_ERR_PARTIAL:
            $msgInfo = "文件上传不完整";
            break;
        case UPLOAD_ERR_NO_FILE:
            $msgInfo = "没有文件被上传";
            break;
        case UPLOAD_ERR_NO_TMP_DIR:
            $msgInfo = "文件不能被缓存";
            break;
        case UPLOAD_ERR_CANT_WRITE:
            $msgInfo = "文件写入失败";
            break;
        case UPLOAD_ERR_EXTENSION:
            $msgInfo = "File upload stopped by extension";
            break;
        default:
            $msgInfo = "Unknown upload error";
            break;
    endswitch;
    if($msgInfo):
        $state['msgInfo'] = $msgInfo;
        echo json_encode($state);
        exit;
    endif;
    if(!is_uploaded_file($_FILES['file']['tmp_name'])):
        $state['msgInfo'] = '上传文件必须是post上传';
        echo json_encode($state);
        exit;
    endif;
    
    $state['errorState'] = 'fileCreateFail';//权限错误
    $state['msg'] = '权限错误';
    //默认上传只需要存放在缓存目录,完成之后需要将文件移动
    $runTimePath =  '/mnt/www/rest/runtime/cache/tmp/'.$uuid;//缓存目录
    if (!file_exists($runTimePath)):
        if(!mkdir($runTimePath,0777,true)):
            $state['msgInfo'] = '缓存目录创建失败';
            echo json_encode($state);
            exit;
        endif;
    endif;
    
    $rootPath =  '/mnt/www/sns/data/uploads/';
    $savePath = 'original/music/' . date('Y');
    if (!file_exists($rootPath.$savePath)):
        if(!mkdir($rootPath.$savePath,0777,true)):
            $state['msgInfo'] = '文件保存目录创建失败';
            echo json_encode($state);
            exit;
        endif;
    endif;
    
    
    $state['errorState'] = 'fragmentFail';//文件单独片验证失败
    $state['msg'] = '文件单片验证失败';
    //以上是文件发送请求基本的参数验证
    if(md5_file($_FILES['file']['tmp_name']) != $md5):
        $state['n'] = $n;
        $state['start'] = $start;
        $state['end'] = $end;
        $state['msgInfo'] = '检验文件失败';
        echo json_encode($state);
        exit;
    endif;
    
    
    $runtimeFileName = $runTimePath.'/'.$md5.'_'.$n;
    $state['msg'] = '';
    $state['errorState'] = '';
    if(!file_exists($runtimeFileName)):
        @move_uploaded_file($_FILES['file']['tmp_name'],$runtimeFileName);
        $state['state'] = true;
    else:
        $state['state'] = true;
    endif;
    //最后一次请求的确认条件
    if($flag == 2 && $fileAllMd5 != null):
        $fileSortArr = [];
        if(is_dir($runTimePath)):
            if($dh = @opendir($runTimePath)):
                while (($file = @readdir($dh)) !== false):
                    if(is_file($runTimePath.'/'.$file) && strpos($file,'_') !== false):
                        $tmp = explode('_',$file);
                        $fileSortArr [$tmp[1]] = $file;
                    endif;
                endwhile;
                ksort($fileSortArr);//排序需要保持下标索引的值
                $savePath .= '/' . $uid . '_' . strtotime(date('Y-m-dHis')) . '.' . $ext;
                $saveFileFp = @fopen($runTimePath.'/'.$md5Name,'wb');//打开即将保存的文件
                if(!$saveFileFp):
                    $state['errorState'] = 'fileCreateFail';//权限错误
                    $state['msg'] = '权限错误';
                    $state['msgInfo'] = '文件句柄打开失败';
                    echo json_encode($state);
                    exit;
                endif;
                foreach ($fileSortArr as $key => $value):
                    $fp = @fopen($runTimePath.'/'.$value, "rb");
                    if(!$fp):
                        $state['errorState'] = 'fileCreateFail';//权限错误
                        $state['msg'] = '权限错误';
                        $state['msgInfo'] = '文件句柄打开失败';
                        echo json_encode($state);
                        exit;
                    endif;
                    if (@flock($fp, LOCK_EX)): // 进行排它型锁定
                        $cont = @fread($fp, filesize($runTimePath.'/'.$value));
                        if(!@fwrite($saveFileFp,$cont)):
                            $state['errorState'] = 'fileCreateFail';//权限错误
                            $state['msg'] = '权限错误';
                            $state['msgInfo'] = '文件拼接错误';
                            echo json_encode($state);
                            exit;
                        endif;
                        @flock($fp, LOCK_UN);    //释放锁定
                    else:
                        $state['errorState'] = 'fileCreateFail';//权限错误
                        $state['msg'] = '权限错误';
                        $state['msgInfo'] = "文件锁定失败";
                        echo json_encode($state);
                        exit;
                    endif;
                    @fclose($fp);
                endforeach;
                unset($value);
                @fclose($saveFileFp);
                @closedir($dh);
                //判断合并之后的文件是否异常
                $phpFileMd5Str = md5_file($runTimePath.'/'.$md5Name);
                if($phpFileMd5Str != $fileAllMd5):
                    $state['state'] = false;
                    $state['errorState'] = 'fileVerifyFail';//文件校验失败
                    $state['msg'] = '文件校验失败';
                    $state['msgInfo'] = '文件上传受损';
                    $state['phpFileMd5Str'] = $phpFileMd5Str;
                    $state['fileAllMd5'] = $fileAllMd5;
                    echo json_encode($state);
                    exit;
                endif;
                if(!rename($runTimePath.'/'.$md5Name,$rootPath.$savePath)):
                    $state['state'] = false;
                    $state['errorState'] = 'moveFail';//文件移动失败
                    $state['msg'] = '文件移动失败';
                    $state['msgInfo'] = '文件移动失败';
                    echo json_encode($state);
                    exit;
                endif;
                $state['state'] = true;
                $state['savePath'] = $savePath;
            else:
                $state['errorState'] = 'fileCreateFail';//权限错误
                $state['msg'] = '权限错误';
                $state['msgInfo'] = '目录打开失败,请重新尝试';
            endif;
        else:
            $state['errorState'] = 'fileCreateFail';//权限错误
            $state['msg'] = '权限错误';
            $state['msgInfo'] = '文件目录异常,请重新尝试';
        endif;
    endif;
    echo json_encode($state);
    exit;



    以上是源码部分,仅仅包含简单的注释.

    展开全文
  • 计算文件 MD5

    千次阅读 2019-09-16 15:19:22
    本篇文章的重点:拿到 File 对象之后,如何计算文件的 md5 值?几千个文件同时计算,页面卡顿崩溃怎么解决?

    1 效果展示

    在这里插入图片描述

    本篇文章的重点:拿到 File 对象之后,如何计算文件的 md5 值?几千个文件同时计算,页面卡顿崩溃怎么解决?

    不知道如何获取 File 对象可以看这篇文章:上传三合一:拖拽上传、上传文件、上传文件夹,一次搞定!,这里不再复述了。

    2 分析

    懒了,不一步步说明了,直接放结论。

    2.1 计算 MD5

    直接用轮子 js-spark-md5

    2.2 解决页面卡顿问题

    同时计算很多文件,页面卡顿崩溃,怎么办?

    主要有两方面的压力:计算压力和渲染压力。

    2.2.1 计算压力:

    缓解计算压力,有下面三种策略:

    策略
    分块缓解大文件造成的计算压力
    文件很大时,一次性读取整个文件非常非常耗时,而且读取时页面会卡死。
    所以必须要分块读取文件,并计算md5。( js-spark-md5 支持分块)
    排队缓解文件多造成的计算压力
    同一时刻,只允许运行最多 n 个计算任务,后来的在等待队列中排队。
    多线程使用 Web Worker 多线程计算md5。(安装 worker-loader 包以在 webpack 中使用 Web Worker)
    注意worker用完必须杀掉。不然数量多了之后,即使没在执行计算任务,浏览器也会崩

    分块和排队都必须用。多线程可用可不用。

    2.2.2 渲染压力:

    如果像开头的效果图一样,把所有文件都展示在页面上。那么文件一多,渲染压力就会很大。

    在真实的业务中,渲染压力会更大。举例说一个场景:

    • 选择要上传的文件后,先计算MD5,之后分块上传文件。
    • 上传列表中要展示所有文件的状态,是正在校验可用空间,还是正在排队算MD5等等。(这会导致,每个文件的每次状态改变,浏览器都要重新渲染)
    • 因为是分块上传,所以有上传进度,进度百分比也要在上传列表中展示。(这会导致,每个任务的上传进度每次改变,浏览器都要重新渲染)

    这个场景下,浏览器在上传过程中每时每刻都在不停地重新渲染,卡卡卡。

    计算压力可以通过分块、排队、多线程来缓解,但渲染压力就没办法了。无论如何,几百几千个div一下子添加进来,并且一直在变化,浏览器肯定会卡的。

    解决方法只有一个,就是不要显示太多文件。可以限制单次上传数量,或者上传列表添加分页功能,等等。

    3 代码

    ComputingMd5Factory.js:负责排队,给每个任务安排一个 Web Worker

    
    import ComputingMd5Worker from 'worker-loader!./ComputingMd5Worker.js';
    
    class ComputingMd5Factory{
        constructor() {
            // 等待队列
            this.waitingList = [];
            // 正在工作的数量
            this.workingCount = 0;
            // 最大同时工作的数量
            this.maxWorkingCount = 1;
        }
        addTask(file) {
            if (this.workingCount < this.maxWorkingCount) {
                this.workingCount++;
                this.computeMd5(file);
            } else {
                this.waitingList.push(file);
            }
        }
        // 用 worker 计算 md5
        computeMd5(file) {
            const worker = new ComputingMd5Worker();
            worker.postMessage({ file });
            worker.addEventListener("message", e => {
                if (e.data.isSuccessful) {
                    file.md5 = e.data.md5;
                    if (this.waitingList.length > 0) {
                        // 不释放 workingCount ,直接把等待队列第一个拿进来.
                        // 这样做是为了防止:释放 workingCount 后的瞬间有新任务 addTask ,插队了
                        let newTask = this.waitingList.shift();
                        this.computeMd5(newTask);
                    } else {
                        this.workingCount--;
                    }
                    // 立刻终止worker
                    worker.terminate();
                } else if (e.data.isFailed) {
                    // 立刻终止worker
                    worker.terminate();
                }
            });
        }
    }
    export default ComputingMd5Factory;
    

    ComputingMd5Worker.js:worker文件,分块读取文件计算 md5。

    
    import SparkMD5 from 'spark-md5'
    
    const blobSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice;
    
    // Read in chunks of 2MB
    const chunkSize = 1024 * 1024 * 1024;
    
    self.addEventListener("message", e => {
        computeMd5(e.data.file).then(md5 => {
            self.postMessage({
                isSuccessful: true,
                md5: md5
            });
        }).catch(message => {
            self.postMessage({
                isFailed: true,
                message
            });
        })
    });
    
    function computeMd5(file) {
        return new Promise((resolve, reject) => {
            var chunksCount = Math.ceil(file.size / chunkSize);
            var currentChunk = 0;
            var spark = new SparkMD5.ArrayBuffer();
            var fileReader = new FileReader();
            fileReader.onload = e => {
                spark.append(e.target.result);
                currentChunk++;
                if (currentChunk < chunksCount) {
                    loadNext();
                } else {
                    const md5 = spark.end();
                    // 成功了
                    resolve(md5);
                }
            };
            fileReader.onerror = e => {
                // 出错了
                reject("Something went wrong when reading the file");
            };
            function loadNext() {
                var start = currentChunk * chunkSize;
                var end = Math.min(start + chunkSize, file.size);
    
                fileReader.readAsArrayBuffer(blobSlice.call(file, start, end));
            }
            loadNext();
        });
    }
    
    展开全文
  • FTP-实例(Md5验证)

    2018-06-05 00:28:00
    print("server file md5", server_file_md5) print("client file md5", new_file_md5) client.close()   上面是客户端FTP_client.py 转载于:https://www.cnblogs.com/fuyuteng/p/9136731.html
  • 5. logoff---------注销命令 6. shutdown-------60秒倒计时关机命令 7. lusrmgr.msc----本机用户和组 8. services.msc---本地服务设置 9. oobe/msoobe /a----检查XP是否激活 10. notepad--------打开记事本 11...
  • 2021年前端面试题及答案

    万次阅读 多人点赞 2020-02-11 19:29:34
    5、前端跨域问题 6、前端数据加密 7、前端http相关问题 8、*前端基础知识点面试题 9、前端技术栈问题 前言 由于新冠肺炎疫情,现在成天呆在家里,加上也要准备面试,就在家里看面试题...
  • 通过layui框架的上传功能,在上传选择文件后,使用 选择文件回调 ,对文件进行md5加密,再上传时,使用 文件上传前的回调 把md5值赋给文件,和数据一并上传 (注意:他的上传方式为post请求 ) 代码: test.html <...
  • 怎么查看视频的md5

    千次阅读 2019-06-30 18:45:03
    怎么查看视频的md5值 在上传背景图片时具有自动剪切功能非常方便 点击关注祥瑞自媒体,了解更多视频操作方面干货 在当前形势之下,工欲善其事必先利其器,软件的作用就显得尤为重要 短视频操作中,...
  • 手机怎么查看视频的MD5

    千次阅读 2019-06-30 17:17:15
    手机怎么查看视频的MD5 标题对一些排水营销账户毫不留情 点击关注祥瑞自媒体,了解更多视频操作方面干货 在当前形势之下,工欲善其事必先利其器,软件的作用就显得尤为重要 短视频操作中,视频修改的...
  • SpringCloud

    千次阅读 2019-11-18 08:54:06
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ia5iSekQ-1574038415836)(D:\TinkingCat\SpringCloud\assets\1571138581444.png)] 微服务介绍 说到微服务,我们先来看看dubbo官网得一张图,...
  • 前段时间简单写了一篇关于上传服务器的文章“大型视频网站的文件上传和断点续传是如何实现的”,引起了很多同行程序猿的关注,大家都在关心实现的原理,下面我来解释一下。 整个功能模块的实现原理其实很简单: 首先...
  •   文件秒传的实现原理其实就是在文件上传前,把内容读取出来,算出 md5 值,然后通过 ajax 与服务端进行验证, 然后根据结果选择继续上传还是跳过上传 js-spark-md5   虽然百度的WebUploader也能够计算文件Md5,...
  • JAVA上百实例源码以及开源项目

    千次下载 热门讨论 2016-01-03 17:37:40
    第一步:运行ServerData.java 启动服务器,然后服务器处于等待状态 第二步:运行LoginData.java 启动(客户端)登陆界面 输入用户名 ip为本机localhost 第三步:在登陆后的界面文本框输入文本,然后发送 可以同时启动...
  • 1、下载空白包 2、用自己应用的签名文件(.keystore或.jks)进行签名,步骤如下(应用宝为例) (1)进入到签名文件的路径下, (2)签名:jarsigner -verbose -keystore xxx.jks -...3、签名后进行上传等待审核
  • 再整理图片上传发现blob流转base64图片预览上传到thinkphp5的文章很少,这次整理一个,希望对大家有帮助 1.使用了Bootstrap的filestyle的上传插件,layui的参考我其他的文章,对了记得引入bootstrap-filestyle.js...
  • HTML5完整版本上传示例

    千次阅读 2016-10-10 11:24:37
    HTML5完整上传示例本身用flash插件一直上传,但是有很多场景不兼容,有些...*MD5校验 服务器反馈信息展示 可控制上传顺序 多视图切换 这里还是申明一下插件核心组件出处CFUpdate (0.8.2 Base)HTML5 批量上传组件 HTML
  • 图片的上传,需要验证MD5,相同图片不会上传(指图片上传,文件名相同会判断MD5,如果MD5相同则不上传,返回该图片URL)。当遇到图片名称冲突时,自动重命名图片并上传,避免出现新图片覆盖旧图片情况。不用下载啥...
  • tp5大文件上传

    千次阅读 2018-09-28 08:52:29
    '等待上传...</p>' + '</div>' ); }); // 文件上传过程中创建进度条实时显示。 uploader.on( 'uploadProgress', function( file, percentage ) { var $li = $( '#'+file.id ), $percent = $li.find('.layui-...
  • linux命令大全

    千次阅读 2015-12-24 08:44:14
    Linux命令大全完整版 目 录 目 录... I 1. linux系统管理命令... 1 adduser1 chfn(change finger information)1 chsh(change shell)1 ...5 ...fwhois5 gitps(gnu interactive tools proce
  • HDFS详解

    千次阅读 多人点赞 2019-10-31 10:43:51
    文件上传HDFS的时候,Client将文件切分成一个一个的Block,然后进行存储;  (2)与NameNode交互,获取文件的位置信息;  (3)与DataNode交互,读取或者写入数据;  (4) Client 提供一些命令来管理 ...
  • editormd 支持拖放上传图片和视频

    千次阅读 2018-07-12 21:12:06
    editormd 支持拖放上传图片和视频 在editormd中,有时觉得 点击按钮 =&amp;amp;gt; 弹出对话框 =&amp;amp;gt; 选择文件这样的上传步骤有些麻烦,要是能支持文件拖放上传,将会是非常不错的用户体验。 实现...
  • PHP大文件上传(切片上传

    万次阅读 2017-08-25 17:42:26
    于是考虑将文件进行切片,然后将切片后的文件统一上传至文件目录,待全部上传成功之后再将其合并成一个文件,同时后台md5验证是否上传成功。 上面的思路是目前上传大容量文件的主要解决方法。 考虑到此种方案,在各...
  • 文章目录前言一、环境准备及依赖库二、项目结构三、 功能实现1、axios二次封装2、 单文件上传FROM-DATA,先选文件再上传3、 单文件上传BASE64,只能上传小于100K的png或jpg图片文件4、多文件上传FORM-DATA5、多文件...
  • 本人在2010年时使用swfupload为核心进行文件的批量上传的解决方案。见文章:WEB版一次选择多个文件进行批量上传(swfupload)的解决方案。 本人在2013年时使用plupload为核心进行文件的批量上传的解决方案。见文章:...
  • 前段时间做了个网盘,所以添加了一个大文件上传接口,这里记录一下 直接给出代码: 前端页面: <!DOCTYPE ...
  • 对于文件上传,相信还有不少同学还停留在FLASH时代,其实现在 HTML5 不仅可以实现文件上传,而且可以做得更好。 以下是对 HTML5 与 FLASH 就文件上传方面的功能调研测试得出的结果。 功能描述 FLASH ...
  • 桶等参数 init 操作类型相关的初始化 检查权限 检查参数 返回头上加上操作的 bucket execute complete 返回 io 的完成状态 记录日志 RGWPutObj(向对象上传数据) 获取 request 中的版本 生成校验 md5 码 检查配额 ...
  • 在开发过程中,收到这样一个问题反馈,在网站上传 100 MB 以上的文件经常失败,重试也要等老半天,这就难为需要上传大规格文件的用户了。那么应该怎么做才能快速上传,就算失败了再次发送也能...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 16,614
精华内容 6,645
关键字:

md5等待上传