[web] 客户端与服务器之间的通信(预览音频文件,上传音频文件和下载音频文件)

近日在做毕设,需要搭建一个完整的平台,用来对外展示组里的语音相关模型(类似这种)。为了实现这种需求,最关键的是客户端(浏览器)和服务端(server)之间能正确地相互通信。如果你学过计算机网络的话,你会发现,承担这项任务的是HTTP request (浏览器-->服务器)和HTTP response (服务器-->浏览器)。对于后者,现在已经有很多成熟的开源后端框架(nginx+django)帮助你在服务器端接收request,处理request,然后生成response返回, 我就不做过多的介绍了,本文的目的主要是为了解决在客户端如何生成request的问题。

在客户端所看到的网页(html+css),实际上是静态的,他们只能用来展示页面,真正从页面中获取信息并制作request的是js文件。通过在html中插入javascript脚本,当某一事件发生时(比如点击某个button),就可以执行这个脚本 :

.html中对应按钮的部分

<div class="waves-effect waves-light btn" id="browse-container">
        <span>Browse files</span>
        <input type="file" id="browse-button" accept="audio/*">
</div>
<div>
        <span>source audio</span>
        <audio id="img-card"  controls></audio><br>
</div>

对应的 .js部分

$("#browse-button").change(function() {
    loadAudio($("#browse-button").prop("files")[0]);
  });

这段的意思是:js通过id(browse-container)来定位html中的某个实体(input),当这个实体发生某种变化(.change)就会执行后面的function。具体到上面的需求中,function要做的就是1:找到音频数据,2:预加载到浏览器缓存中。

找到音频数据并预加载

在upload之前,浏览器必须先读取出本地音频文件的内容到内存中(此时还没开始上传服务器),具体代码如下:

loadAudio = function(file) {
  var reader = new FileReader();
  reader.onload = function(event) {
    $('#img-card').attr('src', event.target.result);
  };
  reader.readAsDataURL(file);
  switchCard(1);
};

实际上file就是前面的$("#browse-button").prop("files")[0] 他传给loadaudio的是音频文件在本地的地址,然后js会创建一个reader以base64字节的方式读取出文件所有的信息,注意此时会把读取的信息赋给上面html中的<audio>的src属性,(event.target.result是一个字符串"data:audio/wav;base64',GFYUGDYUISC...(音频数据的字节流)"此时便可以在浏览器中预听将要上传的音频,如下图所示(注意在loadaudio执行之前,由于src属性为空,audio块会是灰色的)

上传音频数据并显示下载的新音频

得到想上传的音频后,接下来要做的就是为它制作request并能接收服务器返回的response,在js中,ajax()可以完成这两项工作:

upload and detect audio按钮对应的.html

<div class="waves-effect waves-light btn" id="upload-button" >
        <span>Upload and Detect Audio</span>
</div>

相应的.js

  $('#upload-button').click(function() {
    $('.modal').modal('open');
  });

  $('.modal').modal({
    dismissible: false,
    ready: function(modal, trigger) {
      $.ajax({
        type: "POST",
        url:'VC_api/',
        data: {
          'image64': $('#img-card').attr('src')
        },
        dataType: 'text',

        success: function(data) {
          modal.modal('close');
          loadStats(data);

        },
        error: function(data) {
            modal.modal('close');
            loadStats(data);
        },
      }).always(function() {
        modal.modal('close');
      });
    }
  });

首先js检测到upload-button出现‘点击’事件(此时browse-button的读取音频和预览工作已经完成),开始调用ajax构造request,这个request属于POST请求(因为要向服务器发送数据,如果只是从服务器请求数据,则用GET),data就是之前的<audio>块的src,url就是你请求的服务名。如果成功收到response就会进入success,进而提取出response中的音频数据,否则会进入error。.always是指ajax全部执行完毕后关闭modal(bootstrap中的一个子窗口,这里不需要过多深入)完成后视图:

完整代码

html

{% load staticfiles %}
<html>

<head>
  <title>THU Audio</title>
  <link rel="stylesheet" href="{% static 'css/classify.css' %}" type="text/css" />
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.98.1/css/materialize.min.css" />
  <link href="https://fonts.googleapis.com/css?family=Noto+Sans" rel="stylesheet" />
  <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet" />

  <script  src="https://code.jquery.com/jquery-3.2.1.min.js" integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4=" crossorigin="anonymous"></script>
  <script  src="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.98.1/js/materialize.min.js"></script>
  <script  src="{% static 'js/classify.js' %}"></script>

</head>

<body>
  <div class="container row main-container">
    <div class="col s12 dd-container">
      <div class="card dd-card">
        <div class="card-content black-text file-field">
          <div id="drop-container">
            <i class="material-icons large upload-icon">cloud_upload</i>
            <span class="drag-txt"><b>Drag and drop audio here</b></span>
            <span class="or-txt">or</span>
            <form action="#">
              <div class="waves-effect waves-light btn" id="browse-container">
                <span>Browse files</span>
                <input type="file" id="browse-button" accept="audio/*">
              </div>
            </form>
          </div>
        </div>
      </div>
    </div>
    <div class="col s12 uf-container">
      <div class="card uf-card">
        <span>source audio</span>
        <audio id="img-card"  controls></audio><br>
      </div>
      <div class="waves-effect waves-light btn" id="upload-button" >
        <span>Upload and Detect Audio</span>
      </div>
      <div class="waves-effect waves-light btn" id="go-back">
        <span>Go Back</span>
      </div>
    </div>
    <div class="col s12 dt-container">
      <div class="card dt-card" id="stat-table">

      </div>
      <div class="waves-effect waves-light btn" id="go-start">
        <span>Go Back</span>
      </div>
    </div>
    <div id="modal1" class="modal">
      <div class="modal-content">
        <div style="width: 100%; overflow: hidden;">
          <div style="width: 100px; float: left;">
            <div class="preloader-wrapper big active">
              <div class="spinner-layer spinner-blue-only">
                <div class="circle-clipper left">
                  <div class="circle"></div>
                </div>
                <div class="gap-patch">
                  <div class="circle"></div>
                </div>
                <div class="circle-clipper right">
                  <div class="circle"></div>
                </div>
              </div>
            </div>
          </div>
          <div class="loading-text">
            <h5>Loading...</h5></div>
        </div>
      </div>
    </div>
</body>

</html>

js

 $(document).ready(function() {

  var dropContainer = document.getElementById('drop-container');
  dropContainer.ondragover = dropContainer.ondragend = function() {
    return false;
  };

  dropContainer.ondrop = function(e) {
    e.preventDefault();
    loadAudio(e.dataTransfer.files[0])
  };

  $("#browse-button").change(function() {
    loadAudio($("#browse-button").prop("files")[0]);
  });

  $('.modal').modal({
    dismissible: false,
    ready: function(modal, trigger) {
      $.ajax({
        type: "POST",
        url:'VC_api/',
        data: {
          'image64': $('#img-card').attr('src')
        },
        dataType: 'text',

        success: function(data) {
          modal.modal('close');
          loadStats(data);

        },
        error: function(data) {
            modal.modal('close');
            loadStats(data);
        },
      }).always(function() {
        modal.modal('close');
      });
    }
  });

  $('#go-back, #go-start').click(function() {
    $('#img-card').removeAttr("src");
    $('#stat-table').html('');
    switchCard(0);
  });

  $('#upload-button').click(function() {
    $('.modal').modal('open');
  });
});

switchCard = function(cardNo) {
  var containers = [".dd-container", ".uf-container", ".dt-container"];
  var visibleContainer = containers[cardNo];
  for (var i = 0; i < containers.length; i++) {
    var oz = (containers[i] === visibleContainer) ? '1' : '0';
    $(containers[i]).animate({
      opacity: oz
    }, {
      duration: 200,
      queue: false,
    }).css("z-index", oz);
  }
};

loadAudio = function(file) {
  var reader = new FileReader();
  reader.onload = function(event) {
    $('#img-card').attr('src', event.target.result);
  };
  reader.readAsDataURL(file);
  switchCard(1);
};

loadStats = function(jsonData) {
  switchCard(2);
  var data = JSON.parse(jsonData);
  if (data["success"] == true) {

      var markup = `
      <span>source audio</span><br>
      <audio id="result" src="/static/audio/test.wav" controls></audio><br>
      <span>target audio</span><br>
      <audio id="result2" src="/static/audio/y_test.wav" controls></audio><br>
      
      `;
      $("#stat-table").append(markup);

  }
};

 

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值