JavaScript的readAsArrayBuffer返回空的数组缓冲区

11
我试图使用FileReader的readAsArrayBuffer属性来读取本地文件。 读取成功,在“onload”回调中,我可以在reader.result中看到Array Buffer对象。但是Array Buffer为空,虽然长度已设置,但数据没有。我该如何获取这些数据?
这是我的代码:
<!DOCTYPE html>
<html>

<body>
    <input type="file" id="file" />
</body>

<script>
    function handleFileSelect(evt) {

        var files = evt.target.files; // FileList object

        var selFile = files[0];
        var reader = new FileReader();
        reader.onload = function(e) {
            console.log(e.target.result);
        };

        reader.onerror = function(e) {
            console.log(e);
        };
        reader.readAsArrayBuffer(selFile);
    }


    document.getElementById('file').addEventListener('change', handleFileSelect, false);
</script>

</html>

读取器结果的控制台输出

e.target.result
ArrayBuffer {}
e.target.result.byteLength
25312

有人能告诉我如何获取这些数据吗? 有安全问题吗? 没有错误,onerror未执行。

来自评论:请问如何访问缓冲区内容?我正在尝试使用AudioContext播放音频文件...为此我需要缓冲区数据...


1
你为什么认为缓冲区是空的?你的代码实际上根本没有访问/检查缓冲区内容。也许你被 console.log 的输出所迷惑了? console.log() 不会打印缓冲区的内容。 - nmaier
谢谢nmaier, 我也是这么想的...但我不知道如何访问缓冲区内容... 你能告诉我如何访问缓冲区内容吗? 我正试图使用AudioContext播放音频文件... 为此,我需要缓冲数据... 非常感谢你的帮助。 - Anand N
1
你正在使用 onload 事件而不是 onloadend 事件。如果你将 onload 事件替换为 onloadend,你的代码将能够正常工作。请参考:https://developer.mozilla.org/en-US/docs/Web/API/FileReader - seb
@seb 这不是问题所在。我使用的文件已经损坏了...请检查我对nmaier的回复。 - Anand N
2个回答

8

以下是如何读取数组缓冲并将其转换为二进制字符串:

function onfilechange(evt) {
var reader = new FileReader(); 
reader.onload = function(evt) {
  var chars  = new Uint8Array(evt.target.result);
  var CHUNK_SIZE = 0x8000; 
  var index = 0;
  var length = chars.length;
  var result = '';
  var slice;
  while (index < length) {
    slice = chars.subarray(index, Math.min(index + CHUNK_SIZE, length)); 
    result += String.fromCharCode.apply(null, slice);
    index += CHUNK_SIZE;
  }
  // Here you have file content as Binary String in result var
};
reader.readAsArrayBuffer(evt.target.files[0]);
}

如果您尝试通过console.log打印ArrayBuffer,您将始终得到空对象{}。


你如何将二进制字符串转换为数组缓冲区? - Satyam S

5

使用 AudioContext 播放声音并不难。

  1. 设置上下文。
  2. 将任何数据加载到缓冲区(例如,对于本地文件使用 FileReader,对于远程内容使用 XHR)。
  3. 设置新的源并启动它。

总之,像这样:

var context = new(window.AudioContext || window.webkitAudioContext)();

function playsound(raw) {
    console.log("now playing a sound, that starts with", new Uint8Array(raw.slice(0, 10)));
    context.decodeAudioData(raw, function (buffer) {
        if (!buffer) {
            console.error("failed to decode:", "buffer null");
            return;
        }
        var source = context.createBufferSource();
        source.buffer = buffer;
        source.connect(context.destination);
        source.start(0);
        console.log("started...");
    }, function (error) {
        console.error("failed to decode:", error);
    });
}

function onfilechange(then, evt) {
    var reader = new FileReader();
    reader.onload = function (e) {
        console.log(e);
        then(e.target.result);
    };
    reader.onerror = function (e) {
        console.error(e);
    };
    reader.readAsArrayBuffer(evt.target.files[0]);
}


document.getElementById('file')
  .addEventListener('change', onfilechange.bind(null, playsound), false);

在Firefox和Chrome浏览器中,您可以点击jsfiddle查看实时演示。

我为了保险起见添加了console.log(new Uint8Array()),因为浏览器通常会直接记录内容(如果缓冲区不是很大)。有关使用ArrayBuffer的其他功能,请参见相关的MDN文档


我也做了同样的事情,但在播放声音时出现错误... 您给我的小提琴也出现了相同的错误。以下是控制台输出`ProgressEvent正在播放以Uint8Array[10]开头的声音解码失败:null` - Anand N
也许您正在尝试加载某些不受支持的文件格式?并非所有浏览器(在所有平台上)都支持所有音频格式。正如我所说:我在OSX 10.9上的Chrome和Firefox(29和Nightly)中测试了这个小工具,它对我有效。 - nmaier
哦不,我明白问题了, 我尝试播放mp3文件和ogg文件。 它们似乎是损坏的。我从同一个网站下载这些文件,这个网站是我在寻找一些音频示例时找到的...... 我尝试了很多替代方案,认为代码有问题,这浪费了我的一整天...... 我将尝试播放其他文件,看看是否可以正常工作... - Anand N
是的,使用另一个文件它可以工作... 我感觉很糟糕 :( 感谢 nmaier 的时间,非常感激。 - Anand N
这让我抓狂了。最后我发现不能直接访问结果中的数组缓冲区。相反,使用 data = new Uint8Array(reader.result) 就可以解决问题。 - bobbdelsol

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接