AngularJS - 从base64下载文件

时间:2016-05-23 10:00:36

标签: javascript angularjs base64

我尝试将文件编码为base64,然后允许用户下载同一文件的解码版本(只为我培训;-))

但是,当我打开文件时,内容会显示文本" undefined"而不是最初编码的文件的内容。

我在这里做错了什么,我该如何解决?

HTML

<form ng-submit="upload(file)">
    <input type="file" ng-model="file">
    <button type="submit" class="button success pull-right"><i class="glyphicon glyphicon-ok"></i> Add</button>
</form>
<ul>
    <li ng-repeat="link in downloads track by $index">
        <a href="{{ link.link }}" download="{{ link.link }}">{{ link.name }}<a>
    </li>
</ul>


控制器

angular.module('myApp')
.controller('testController', function ($scope) {
    $scope.upload = function(file){
        var contentType = 'text/plain';
        var b64Data = encode64(file);

        var blob = b64toBlob(b64Data, contentType);
        addLink(URL.createObjectURL(blob));
    }

    $scope.downloads = [];
    function addLink(linkAddress){
        $scope.downloads.push({
            link: linkAddress,
            name: 'test ' + ($scope.downloads.length+1)
        });
    }

    function b64toBlob(b64Data, contentType, sliceSize) {
      contentType = contentType || '';
      sliceSize = sliceSize || 512;

      var byteCharacters = decode64(b64Data);
      var byteArrays = [];

      for (var offset = 0; offset < byteCharacters.length; offset += sliceSize) {
        var slice = byteCharacters.slice(offset, offset + sliceSize);

        var byteNumbers = new Array(slice.length);
        for (var i = 0; i < slice.length; i++) {
          byteNumbers[i] = slice.charCodeAt(i);
        }

        var byteArray = new Uint8Array(byteNumbers);

        byteArrays.push(byteArray);
      }

      var blob = new Blob(byteArrays, {type: contentType});
      return blob;
    }

    function encode64(input) {
        input = escape(input);
        var output = "";
        var chr1, chr2, chr3 = "";
        var enc1, enc2, enc3, enc4 = "";
        var i = 0;
        var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";

        do {
            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 +
               keyStr.charAt(enc1) +
               keyStr.charAt(enc2) +
               keyStr.charAt(enc3) +
               keyStr.charAt(enc4);
            chr1 = chr2 = chr3 = "";
            enc1 = enc2 = enc3 = enc4 = "";
        } while (i < input.length);

        return output;
    }

    function decode64(input) {
        var output = "";
        var chr1, chr2, chr3 = "";
        var enc1, enc2, enc3, enc4 = "";
        var i = 0;
        var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";

        // remove all characters that are not A-Z, a-z, 0-9, +, /, or =
        var base64test = /[^A-Za-z0-9\+\/\=]/g;
        if (base64test.exec(input)) {
            console.error("There were invalid base64 characters in the input text.\n" +
                "Valid base64 characters are A-Z, a-z, 0-9, '+', '/',and '='\n" +
                "Expect errors in decoding.");
        }
        input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");

        do {
            enc1 = keyStr.indexOf(input.charAt(i++));
            enc2 = keyStr.indexOf(input.charAt(i++));
            enc3 = keyStr.indexOf(input.charAt(i++));
            enc4 = 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);
            }

            chr1 = chr2 = chr3 = "";
            enc1 = enc2 = enc3 = enc4 = "";

        } while (i < input.length);

        return unescape(output);
    }
});

1 个答案:

答案 0 :(得分:2)

您必须使用FileReader来实际读取文件的内容。 我还创建了一个承诺(使用AngularJS&#39; s $q),当FileReader完成加载文件内容并对其进行编码时,它会解析。

document.getElementById()获取fileInput元素并不是一种有角度的方式,但是你可以根据自己的想法进行练习。

我调整了你的代码:

function encode64() {
    var fileInput = document.getElementById('fileInput');
    var file = fileInput.files[0];
    var deferred = $q.defer();

    var reader = new FileReader();
    reader.onload = function(e) {
        var input = reader.result;

        var output = "";
        var chr1, chr2, chr3 = "";
        var enc1, enc2, enc3, enc4 = "";
        var i = 0;
        var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";

        do {
            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 +
                keyStr.charAt(enc1) +
                keyStr.charAt(enc2) +
                keyStr.charAt(enc3) +
                keyStr.charAt(enc4);
            chr1 = chr2 = chr3 = "";
            enc1 = enc2 = enc3 = enc4 = "";
        } while (i < input.length);
        deferred.resolve(output);
    }
    reader.readAsText(file);
    return deferred.promise;
}

$scope.upload = function() {
    var contentType = 'text/plain';
    encode64().then(function(b64Data){
        var blob = b64toBlob(b64Data, contentType);
        addLink(URL.createObjectURL(blob));
    });
}