简体   繁体   中英

Base64 - File is damaged

I'm trying to upload a pdf file through javascript. I have the base64 representation of the file and I decode it. The file is uploaded but that data seems to be corrupt.

The error message says "The file is damaged and could not be repaired" when I try opening the file.

I get the base64 string server side like so...

byte[] buffer = new byte[length];  
var postedFile = httpRequest.Files[file];                 
postedFile.InputStream.Read(buffer, 0, length);
string encodedString = Convert.ToBase64String(buffer);

Here is the ajax call I make to upload the file

var data= Base64.decode(result); //result is the base64 encoded string
 $.ajax({
                    url: url,
                    type: "POST",
                    data: data,
                    processData: false,
                    headers: {
                        "accept": "application/json;odata=verbose",
                        "X-RequestDigest": _digetsValue,
                        "content-length": length

                    },
                    success: function (data)
                    {
                        alert("it worked");

                    },
                    error: function (err)
                    {

                    }
                });

For decoding, I'm using this chunk of code... or from here How can you encode a string to Base64 in JavaScript?

var Base64 = {
        // private property
        _keyStr: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",

        // public method for encoding
        encode: function (input)
        {
            var output = "";
            var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
            var i = 0;

            input = Base64._utf8_encode(input);

            while (i < input.length)
            {

                chr1 = input.charCodeAt(i++);
                chr2 = input.charCodeAt(i++);
                chr3 = input.charCodeAt(i++);

                enc1 = chr1 >> 2;
                enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
                enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
                enc4 = chr3 & 63;

                if (isNaN(chr2))
                {
                    enc3 = enc4 = 64;
                } else if (isNaN(chr3))
                {
                    enc4 = 64;
                }

                output = output +
                Base64._keyStr.charAt(enc1) + Base64._keyStr.charAt(enc2) +
                Base64._keyStr.charAt(enc3) + Base64._keyStr.charAt(enc4);

            }

            return output;
        },

        // public method for decoding
        decode: function (input)
        {
            var output = "";
            var chr1, chr2, chr3;
            var enc1, enc2, enc3, enc4;
            var i = 0;

            input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");

            while (i < input.length)
            {

                enc1 = Base64._keyStr.indexOf(input.charAt(i++));
                enc2 = Base64._keyStr.indexOf(input.charAt(i++));
                enc3 = Base64._keyStr.indexOf(input.charAt(i++));
                enc4 = Base64._keyStr.indexOf(input.charAt(i++));

                chr1 = (enc1 << 2) | (enc2 >> 4);
                chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
                chr3 = ((enc3 & 3) << 6) | enc4;

                output = output + String.fromCharCode(chr1);

                if (enc3 != 64)
                {
                    output = output + String.fromCharCode(chr2);
                }
                if (enc4 != 64)
                {
                    output = output + String.fromCharCode(chr3);
                }

            }

            output = Base64._utf8_decode(output);

            return output;

        },

        // private method for UTF-8 encoding
        _utf8_encode: function (string)
        {
            string = string.replace(/\r\n/g, "\n");
            var utftext = "";

            for (var n = 0; n < string.length; n++)
            {

                var c = string.charCodeAt(n);

                if (c < 128)
                {
                    utftext += String.fromCharCode(c);
                }
                else if ((c > 127) && (c < 2048))
                {
                    utftext += String.fromCharCode((c >> 6) | 192);
                    utftext += String.fromCharCode((c & 63) | 128);
                }
                else
                {
                    utftext += String.fromCharCode((c >> 12) | 224);
                    utftext += String.fromCharCode(((c >> 6) & 63) | 128);
                    utftext += String.fromCharCode((c & 63) | 128);
                }

            }

            return utftext;
        },

        // private method for UTF-8 decoding
        _utf8_decode: function (utftext)
        {
            var string = "";
            var i = 0;
            var c = c1 = c2 = 0;

            while (i < utftext.length)
            {

                c = utftext.charCodeAt(i);

                if (c < 128)
                {
                    string += String.fromCharCode(c);
                    i++;
                }
                else if ((c > 191) && (c < 224))
                {
                    c2 = utftext.charCodeAt(i + 1);
                    string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
                    i += 2;
                }
                else
                {
                    c2 = utftext.charCodeAt(i + 1);
                    c3 = utftext.charCodeAt(i + 2);
                    string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
                    i += 3;
                }

            }
            return string;
        }
    }

Originally, I was doing something like this...

getFileBuffer = function (file)
{
    var deferred = $.Deferred();
    var reader = new FileReader();
    reader.onload = function (e)
    {
        deferred.resolve(e.target.result);
    }
    reader.onerror = function (e)
    {
        deferred.reject(e.target.error);
    }
    reader.readAsArrayBuffer(file);

    return deferred.promise();
};

But of course this is exclusive to HTML5 and whatnot. So when I would call my ajax function, I would pass in this arraybuffer from the file reader and voila! It would work. Now I'm trying to mimic the same sort of functionality with IE8. Is this possible?

Thanks

I wrote some functions a while ago I believe to be binary safe, here are the relevant ones for you; base64To6 and (perhaps poorly named) base6To8 .

var chars = (
        'ABCDEFGHIJKLMNOPQRSTUVWXYZ' +
        'abcdefghijklmnopqrstuvwxyz' +
        '0123456789+/'
    ),
    inver = {}, i;
for (i = 0; i < chars.length; ++i) {
    inver[chars[i]] = i;
}

function base64To6(b64) {
    var arr6 = [],
        i = b64.length, lenMod = 0;
    while (b64.charAt(--i) === '=')
        ++lenMod;
    for (i = 0; i < b64.length - lenMod; ++i)
        arr6.push(inver[b64.charAt(i)]);
    i = b64.length & 3;
    if (i) i = 4 - i;
    i = i + b64.length;
    arr6.byteLength = 3 * i / 4 - lenMod;
    return arr6;
}

function base6To8(arr6) {
    var arr8 = [], i,
        e1, e2, e3,
        s1, s2, s3, s4,
        d1, d2, d3, d4;
    for (i = 0; i < arr6.length; i += 4) {
        s1 = (d1 = arr6[i]    ) & 63;
        s2 = (d2 = arr6[i + 1]) & 63;
        s3 = (d3 = arr6[i + 2]) & 63;
        s4 = (d4 = arr6[i + 3]) & 63;
        // xxxxxx xxyyyy yyyyzz zzzzzz
        e1 = ( s1       << 2) + (s2 >>> 4);
        e2 = ((s2 & 15) << 4) + (s3 >>> 2);
        e3 = ((s3 &  3) << 6) +  s4       ;
        arr8.push(e1);
        if (d3 !== undefined)
            arr8.push(e2, e3);
        else if (d2 !== undefined )
            arr8.push(e2);
    }
    if (arr6.byteLength !== undefined)
        arr8.length = +arr6.byteLength;
    return arr8;
}

Now if you do

var int8arr = base6to8(base64to6(data));

You will have an Array of Integers (at most 8 bit numbers), which the Base64 was representing. JavaScript does not use Int8 for Number so you can't immediately use this Array .

Unfortunately, as far as I know, IE8 does not support UInt8Array or Blob , which would let you then happily work with the binary data, so I'm not sure exactly where you'd want to take it from here.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM