javascript - AngularJS - 从base64下载文件

标签 javascript angularjs base64

我正在尝试将文件编码为 base64,然后允许用户下载同一文件的解码版本(对我来说只是一个训练练习 ;-))

但是当我打开文件时,内容显示文本“未定义”而不是文件最初编码的内容。

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

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>


Controller

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);
    }
});

最佳答案

您必须使用 FileReader 才能实际读取文件的内容。 我还创建了一个 promise (使用 AngularJS 的 $q ),当 FileReader 完成加载文件内容并对它们进行编码时解析。

获取每个 document.getElementById() 的 fileInput 元素不是 Angular 方式,但你会得到练习的想法。

我已经修改了你的代码:

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));
    });
}

关于javascript - AngularJS - 从base64下载文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37387994/

相关文章:

angularjs - 页面无法正常显示

python - 为什么 Python 的 base64.b64decode() 会忽略字符串末尾的乱码?

java - 通过 POST 将 ZIP 文件发送到 Base64 中的服务器

python - 在Python中调整base64图像的大小

java - java如何获取响应对象

javascript - 从 PhantomJS onLoadFinished 回调调用函数

javascript - 在我选择一个值后,更改问题仍然存在

javascript - FabricJS - 组选择在选择时将对象带到前面

javascript - 将 JSON 解析为 HTML 表

javascript - angularjs 清理以仅删除 JS