首页 > 建站教程 > APP开发,混合APP >  apicloud将录音文件转成base64正文

apicloud将录音文件转成base64

在写这篇文章之前,先来个前提条件:因为这个项目是警用项目,只有内网能用,其次是请求的时候要经过一个中转,而这个中转就导致了无法发送文件,只能以base64传输。也就是说,录音,得到文件地址,根据地址将录音文件转成base64,只能在前端完成,既不能指望将文件传给第三方,也不能指望传给后台转成base64。

录音很简单,没有用apicloud自带的录音,它只能录制amr格式,所以用了一个叫“recMp3”的模块,它可以录mp3格式,代码如下:
//录音
var recMp3 = api.require('recMp3');
recMp3.start(function(ret, err) {
    if (ret) {
        if(ret.db!=undefined){
        }
    } else {
        func.msg(err.message);
    }
});

//停止录音
var that = this;
var recMp3 = api.require('recMp3');
recMp3.stop(function(ret,err) {
    if(ret){
        var duration = ret.duration;
        //得到fs://格式的录音地址
        var path = ret.path;
    }
});
将mp3格式音乐转成base64也简单:
let fileReader = new FileReader();
fileReader.readAsDataURL(mp3文件)
fileReader.onload = function (e){
    //得到mp3文件的base64
    var base64Data = e.target.result;
};
最关键的来了,这个mp3文件如何得到,recMp3录音成功后,只返回了一个fs://格式的地址,而fileReader.readAsDataURL传地址是不行的。

首先就想到了<input type="file" />的方法获取,但是这种方法不行,因为它必须要用户点击,然后弹窗,然后选择文件才可以。而浏览器也出于安全,是不会让开发者在避开用户的情况下,轻易得到本地文件。那只能另辟蹊径。于是想到了ajax,ajax可以用来下载文件,并且返回此文件的blob格式,只要在responseType设置为blob就行了,于是,我爱模板网写了下面的代码:
//通过原生ajax获取网络音乐,并转为base64
var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://www.5imoban.net/view/demomusic/niliuchenghe.mp3');
xhr.responseType = 'blob';
xhr.send();
xhr.onload = function() {
    let fileReader = new FileReader();
    fileReader.readAsDataURL(xhr.response)
    fileReader.onload = function (e){
        //下面的代码成功得到了mp3格式文件的base64格式
        console.log(e.target.result);
    };
};
上面代码成功了!因为是apicloud项目,不用考虑跨域问题。现在的问题就变成了,请求fs或者widget格式的路径行不行。结果打脸了,这个ajax是js原生的,肯定不识别fs或者widget,因为那是app的路径。而apicloud提供的ajax又不支持返回blob。于是又换成相对路径试下,因为js原生应该是别相对路径,发现成功了:
//通过相对地址获取本地文件,并转为base64
var xhr = new XMLHttpRequest();
xhr.open('GET', '../../js/api.js');
xhr.responseType = 'blob';
xhr.send();
xhr.onload = function() {
    let fileReader = new FileReader();
    fileReader.readAsDataURL(xhr.response)
    fileReader.onload = function (e){
        //下面的代码成功得到了api.js的base64格式
        console.log(e.target.result);
    };
};
现在的问题就是如何将录音的fs协议的地址转换成相对地址了,可以先将fs地址的文件用fs模块,剪切到项目根目录,然后就可以用相对路径了,代码如下:
var pathArr = path.split("/");  //这里的path是录音得到的fs协议的路径
var mp3Name = pathArr[pathArr.length-1];
var fs = api.require('fs');
fs.moveTo({
    oldPath : path,  //这里的path是录音得到的fs协议的路径
    newPath : 'widget://mp3/'
}, function(ret, err) {
    that.mp3Src = '../../mp3/'+mp3Name;  //将mp3移动到widget以便于得到相对路径
});
通过上面的方法得到的mp3Src就是这个录音文件相对于当前文件的相对地址了(当前文件在widget://html/street,而移动后的mp3录音文件在widget://mp3/目录),再此使用上面的方法,就成功得到了!!耗费了一个多小时的时间终于解决了!下面是包含录音、转换base64等的完整代码:
//开始录音
startRecord(){
    var recMp3 = api.require('recMp3');
    recMp3.start(function(ret, err) {
        if (ret) {
            console.log('录音开始');
        } else {
            func.msg(err.message);
        }
    });
},
//结束录音
stopRecord(){
    var that = this;
    var recMp3 = api.require('recMp3');
    recMp3.stop(function(ret,err) {
        if(ret){
            var duration = ret.duration;
            var path = ret.path;
            //得到mp3的名字
            var pathArr = path.split("/");
            var mp3Name = pathArr[pathArr.length-1];
            if(duration>1){
                var fs = api.require('fs');
                //将mp3移动到widget以便于得到相对路径,只有相对路径才能进行本地ajax请求
                fs.moveTo({
                    oldPath : path,
                    newPath : 'widget://mp3/'
                }, function(ret, err) {
                    that.mp32Base64('../../mp3/'+mp3Name);
                });
            }else{
                func.msg('录音时间太短,请重新录制!');
            }
            clearInterval(that.timer);
            that.howLong = 0;
            that.recordState = 3;
        }
    });
},
//mp3转base64
mp32Base64:function(path){
    var that = this;
    var xhr = new XMLHttpRequest();
    xhr.open('GET', path);
    xhr.responseType = 'blob';
    xhr.send();
    xhr.onload = function() {
        let fileReader = new FileReader();
        fileReader.readAsDataURL(xhr.response)
        fileReader.onload = function (e){
            console.log(e.target.result);
            //最终得到mp3的base64
            that.mp3Base64 = e.target.result;
        };
    };
},
至此完成了!此方法不仅仅适用于apicloud,web端也可以。另外,如果不是因为外网被禁,我肯定直接传给后台转base64了,转完了,再发回来。
此外,其实虽然使用ajax成功读取了本地文件,但是仅限于当前项目,如果想用ajax读取项目之外的文件,还是不好弄!