草庐IT

php - 如何使用 pdo 将录制的音频文件上传到数据库

coder 2023-10-22 原文

伙计们!我正在尝试在我的网站中实现录音机。我想要的是让用户将录制的文件直接保存到数据库和我网站中的一个子文件夹(称为/speaking_audios)。主要文件如下:

录音机.php

 <!DOCTYPE html>
<html>
<head lang="en">
  <meta charset="UTF-8">
  <title>FlashWavRecorder demo</title>
  <script src='http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.js'></script>
  <script type="text/javascript" src="js/swfobject.js"></script>
  <script type="text/javascript" src="js/recorder.js"></script>
  <script type="text/javascript" src="js/main.js"></script>
  <link rel="stylesheet" href="css/style.css">

</head>

<body>
  <div class="container">

    <h1><a href="https://github.com/cykod/FlashWavRecorder">FlashWavRecorder</a></h1>
    <p><strong>Upload requires php, i.e. example will not work on github.com</strong></p>


    <div id="recorder-audio" class="control_panel idle">
      <button class="record_button" onclick="FWRecorder.record('audio', 'audio.wav');" title="Record">
        <img src="images/record.png" alt="Record"/>
      </button>
      <button class="stop_recording_button" onclick="FWRecorder.stopRecording('audio');" title="Stop Recording">
        <img src="images/stop.png" alt="Stop Recording"/>
      </button>
      <button class="play_button" onclick="FWRecorder.playBack('audio');" title="Play">
          <img src="images/play.png" alt="Play"/>
      </button>
      <button class="pause_playing_button" onclick="FWRecorder.pausePlayBack('audio');" title="Pause Playing">
          <img src="images/pause.png" alt="Pause Playing"/>
      </button>
      <button class="stop_playing_button" onclick="FWRecorder.stopPlayBack();" title="Stop Playing">
        <img src="images/stop.png" alt="Stop Playing"/>
      </button>
      <div class="level"></div>
    </div>

    <div id="recorder-audio2" class="control_panel idle">
      <button class="record_button" onclick="FWRecorder.record('audio2', 'audio2.wav');" title="Record">
        <img src="images/record.png" alt="Record"/>
      </button>
      <button class="stop_recording_button" onclick="FWRecorder.stopRecording('audio2');" title="Stop Recording">
        <img src="images/stop.png" alt="Stop Recording"/>
      </button>
      <button class="play_button" onclick="FWRecorder.playBack('audio2');" title="Play">
        <img src="images/play.png" alt="Play"/>
      </button>
      <button class="pause_playing_button" onclick="FWRecorder.pausePlayBack('audio2');" title="Pause Playing">
        <img src="images/pause.png" alt="Pause Playing"/>
      </button>
      <button class="stop_playing_button" onclick="FWRecorder.stopPlayBack();" title="Stop Playing">
        <img src="images/stop.png" alt="Stop Playing"/>
      </button>
      <div class="level"></div>
    </div>

    <div class="details">
      <button class="show_level" onclick="FWRecorder.observeLevel();">Show Level</button>
      <button class="hide_level" onclick="FWRecorder.stopObservingLevel();" style="display: none;">Hide Level</button>
      <span id="save_button">
        <span id="flashcontent">
          <p>Your browser must have JavaScript enabled and the Adobe Flash Player installed.</p>
        </span>
      </span>
      <div><button class="show_settings" onclick="microphonePermission()">Microphone permission</button></div>
      <div id="status">
       Recorder Status...
      </div>
      <div>Duration: <span id="duration"></span></div>
      <div>Activity Level: <span id="activity_level"></span></div>
      <div>Upload status: <span id="upload_status"></span></div>
    </div>

    <form id="uploadForm" name="uploadForm" action="upload.php">
      <input name="authenticity_token" value="xxxxx" type="hidden">
      <input name="upload_file[parent_id]" value="1" type="hidden">
      <input name="format" value="json" type="hidden">
    </form>

    <h4>Configure Microphone</h4>
    <form class="mic_config" onsubmit="return false;">
      <ul>
        <li>
          <label for="rate">Rate</label>
          <select id="rate" name="rate">
            <option value="44" selected>44,100 Hz</option>
            <option value="22">22,050 Hz</option>
            <option value="11">11,025 Hz</option>
            <option value="8">8,000 Hz</option>
            <option value="5">5,512 Hz</option>
          </select>
        </li>

        <li>
          <label for="gain">Gain</label>
          <select id="gain" name="gain">
          </select>
        </li>

        <li>
          <label for="silenceLevel">Silence Level</label>
          <select id="silenceLevel" name="silenceLevel">
          </select>
        </li>

        <li>
          <label for="silenceTimeout">Silence Timeout</label>
          <input id="silenceTimeout" name="silenceTimeout" value="2000"/>
        </li>

        <li>
          <input id="useEchoSuppression" name="useEchoSuppression" type="checkbox"/>
          <label for="useEchoSuppression">Use Echo Suppression</label>
        </li>

        <li>
          <input id="loopBack" name="loopBack" type="checkbox"/>
          <label for="loopBack">Loop Back</label>
        </li>

        <li>
          <button onclick="configureMicrophone();">Configure</button>
        </li>
      </ul>
    </form>
  </div>

</body>
</html>

数据库表“记录”SQL结构:

    CREATE TABLE `recordings` (
  `id` int(5) NOT NULL AUTO_INCREMENT,
  `username_id` int(5) NOT NULL,
  `username` varchar(50) NOT NULL,
  `upload_file` longblob NOT NULL,
  `filename` varchar(100) NOT NULL,
  `currenttime` datetime NOT NULL,
  `type` longtext NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;

配置.php

    <?php
try {
    $pdo = new PDO('mysql:host=localhost;dbname=database','root','');
    $pdo->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);

} catch(PDOException $e) {
    echo 'Error: '.$e->getMessage();
}
?>

上传.php

    <?php
$save_folder = dirname(__FILE__) . "/speaking_audios";
if(! file_exists($save_folder)) {
  if(! mkdir($save_folder)) {
    die("failed to create save folder $save_folder");
  }
 }

function valid_wav_file($file) {
  $handle = fopen($file, 'r');
  $header = fread($handle, 4);
  list($chunk_size) = array_values(unpack('V', fread($handle, 4)));
  $format = fread($handle, 4);
  fclose($handle);
  return $header == 'RIFF' && $format == 'WAVE' && $chunk_size == (filesize($file) - 8);
}

$key = 'filename';
$tmp_name = $_FILES["upload_file"]["tmp_name"][$key];
$upload_name = md5(uniqid() .rand()). ".wav";
#$_FILES["upload_file"]["name"][$key];
$type = $_FILES["upload_file"]["type"][$key];
$filename = "$save_folder/$upload_name";
#$filename = "$save_folder/$upload_name";
$saved = 0;
if($type == 'audio/wav' && preg_match('/^[a-zA-Z0-9_\-]+\.wav$/', $upload_name) && valid_wav_file($tmp_name)) {
  $saved = move_uploaded_file($tmp_name, $filename) ? 1 : 0;
}

if($_POST['format'] == 'json') {
  header('Content-type: application/json');
  print "{\"saved\": $saved}";
} else {
  print $saved ? "Saved" : 'Not saved';
}

exit;

# Save a few info to database
include "config.php";

$username = $_SESSION['username'];

$stmt = $pdo->prepare("INSERT INTO `recordings` (username, filename, currenttime) VALUES (:username, :filename, NOW())");
$stmt->execute(array(':username' => $username, ':filename' => $upload_name));

?>

好吧,我只想让你专注于 upload.php 文件,看看我做错了什么。不知道是不是“exit;”这一行引起的问题在 upload.php 文件中。该文件正在保存到子文件夹“/speaking_audios”,但未保存到数据库。为什么?也许问题出在 upload.php 文件行中:

include "config.php";

$upload_file=$upload_name; # also $upload_name
$username_id = $_SESSION['username'];

$stmt = $pdo->prepare("INSERT INTO `recordings` (username, filename, currenttime) VALUES (:username_id, :upload_file, NOW())");
$stmt->execute(array(':username_id' => $username_id, ':upload_file' => $upload_file));

还有javascript中的主音频 Controller :

js/main.js

 $(function () {
  var $uploadStatus = $('#upload_status'),
    $showLevelButton = $('.show_level'),
    $hideLevelButton = $('.hide_level'),
    $level = $('.control_panel .level');

  var CLASS_CONTROLS = "control_panel";
  var CLASS_RECORDING = "recording";
  var CLASS_PLAYBACK_READY = "playback_ready";
  var CLASS_PLAYING = "playing";
  var CLASS_PLAYBACK_PAUSED = "playback_paused";

//  Embedding flash object ---------------------------------------------------------------------------------------------

  setUpFormOptions();
  var appWidth = 24;
  var appHeight = 24;
  var flashvars = {'upload_image': 'images/upload.png'};
  var params = {};
  var attributes = {'id': "recorderApp", 'name': "recorderApp"};
  swfobject.embedSWF("recorder.swf", "flashcontent", appWidth, appHeight, "11.0.0", "", flashvars, params, attributes);

//  Handling FWR events ------------------------------------------------------------------------------------------------

  window.fwr_event_handler = function fwr_event_handler() {
    $('#status').text("Last recorder event: " + arguments[0]);
    var name, $controls;
    switch (arguments[0]) {
      case "ready":
        var width = parseInt(arguments[1]);
        var height = parseInt(arguments[2]);
        FWRecorder.uploadFormId = "#uploadForm";
        FWRecorder.uploadFieldName = "upload_file[filename]";
        FWRecorder.connect("recorderApp", 0);
        FWRecorder.recorderOriginalWidth = width;
        FWRecorder.recorderOriginalHeight = height;
        $('.save_button').css({'width': width, 'height': height});
        break;

      case "no_microphone_found":
        break;

      case "microphone_user_request":
        recorderEl().addClass("floating");
        FWRecorder.showPermissionWindow();
        break;

      case "microphone_connected":
        FWRecorder.isReady = true;
        $uploadStatus.css({'color': '#000'});
        break;

      case "permission_panel_closed":
        FWRecorder.defaultSize();
        recorderEl().removeClass("floating");
        break;

      case "microphone_activity":
        $('#activity_level').text(arguments[1]);
        break;

      case "recording":
        name = arguments[1];
        $controls = controlsEl(name);
        FWRecorder.hide();
        setControlsClass($controls, CLASS_RECORDING);
        break;

      case "recording_stopped":
        name = arguments[1];
        $controls = controlsEl(name);
        var duration = arguments[2];
        FWRecorder.show();
        setControlsClass($controls, CLASS_PLAYBACK_READY);
        $('#duration').text(duration.toFixed(4) + " seconds");
        break;

      case "microphone_level":
        $level.css({width: arguments[1] * 50 + '%'});
        break;

      case "observing_level":
        $showLevelButton.hide();
        $hideLevelButton.show();
        break;

      case "observing_level_stopped":
        $showLevelButton.show();
        $hideLevelButton.hide();
        $level.css({width: 0});
        break;

      case "playing":
        name = arguments[1];
        $controls = controlsEl(name);
        setControlsClass($controls, CLASS_PLAYING);
        break;

      case "playback_started":
        name = arguments[1];
        var latency = arguments[2];
        break;

      case "stopped":
        name = arguments[1];
        $controls = controlsEl(name);
        setControlsClass($controls, CLASS_PLAYBACK_READY);
        break;

      case "playing_paused":
        name = arguments[1];
        $controls = controlsEl(name);
        setControlsClass($controls, CLASS_PLAYBACK_PAUSED);
        break;

      case "save_pressed":
        FWRecorder.updateForm();
        break;

      case "saving":
        name = arguments[1];
        break;

      case "saved":
        name = arguments[1];
        var data = $.parseJSON(arguments[2]);
        if (data.saved) {
          $('#upload_status').css({'color': '#0F0'}).text(name + " was saved");
        } else {
          $('#upload_status').css({'color': '#F00'}).text(name + " was not saved");
        }
        break;

      case "save_failed":
        name = arguments[1];
        var errorMessage = arguments[2];
        $uploadStatus.css({'color': '#F00'}).text(name + " failed: " + errorMessage);
        break;

      case "save_progress":
        name = arguments[1];
        var bytesLoaded = arguments[2];
        var bytesTotal = arguments[3];
        $uploadStatus.css({'color': '#000'}).text(name + " progress: " + bytesLoaded + " / " + bytesTotal);
        break;
    }
  };

//  Helper functions ---------------------------------------------------------------------------------------------------

  function setUpFormOptions() {
    var gain = $('#gain')[0];
    var silenceLevel = $('#silenceLevel')[0];
    for (var i = 0; i <= 100; i++) {
      gain.options[gain.options.length] = new Option(100 - i);
      silenceLevel.options[silenceLevel.options.length] = new Option(i);
    }
  }

  function setControlsClass($controls, className) {
    $controls.attr('class', CLASS_CONTROLS + ' ' + className);
  }

  function controlsEl(name) {
    return $('#recorder-' + name);
  }

  function recorderEl() {
    return $('#recorderApp');
  }


//  Button actions -----------------------------------------------------------------------------------------------------

  window.microphonePermission = function () {
    recorderEl().addClass("floating");
    FWRecorder.showPermissionWindow({permanent: true});
  };

  window.configureMicrophone = function () {
    if (!FWRecorder.isReady) {
      return;
    }
    FWRecorder.configure($('#rate').val(), $('#gain').val(), $('#silenceLevel').val(), $('#silenceTimeout').val());
    FWRecorder.setUseEchoSuppression($('#useEchoSuppression').is(":checked"));
    FWRecorder.setLoopBack($('#loopBack').is(":checked"));
  };

});

保存文件后,recorder.php 中的上传状态后会显示一条绿色消息。那是单击箭头以保存/上传 upload.php 时生效,但未显示。可以说,用户仍留在页面 recorder.php 上。

最佳答案

exit之后的任何东西都不会被执行!

试着删除它...

同样在您的查询之后尝试添加:

if($stmt->errorCode() == 0) {
    echo "success";
} else {
    $errors = $stmt->errorInfo();
    print_r($errors);
}

它可能会给出一些解释。

同时 id 将我的 db execute 放在行之前:

if($_POST['format'] == 'json') {

还注意到您所有的表字段都设置为 NOT NULL,但您只插入了 3 个字段。如果它们留空,将导致错误。

您的 username_id 字段设置为 int,我想您可能正在尝试用可能是 varchar 的用户名填充它

关于php - 如何使用 pdo 将录制的音频文件上传到数据库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34476663/

有关php - 如何使用 pdo 将录制的音频文件上传到数据库的更多相关文章

  1. ruby - 如何使用 Nokogiri 的 xpath 和 at_xpath 方法 - 2

    我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div

  2. ruby - 如何从 ruby​​ 中的字符串运行任意对象方法? - 2

    总的来说,我对ruby​​还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用

  3. ruby - 使用 RubyZip 生成 ZIP 文件时设置压缩级别 - 2

    我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看ruby​​zip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d

  4. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  5. ruby-on-rails - 使用 Ruby on Rails 进行自动化测试 - 最佳实践 - 2

    很好奇,就使用ruby​​onrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提

  6. ruby - 在 Ruby 中使用匿名模块 - 2

    假设我做了一个模块如下:m=Module.newdoclassCendend三个问题:除了对m的引用之外,还有什么方法可以访问C和m中的其他内容?我可以在创建匿名模块后为其命名吗(就像我输入“module...”一样)?如何在使用完匿名模块后将其删除,使其定义的常量不再存在? 最佳答案 三个答案:是的,使用ObjectSpace.此代码使c引用你的类(class)C不引用m:c=nilObjectSpace.each_object{|obj|c=objif(Class===objandobj.name=~/::C$/)}当然这取决于

  7. ruby - 其他文件中的 Rake 任务 - 2

    我试图在一个项目中使用rake,如果我把所有东西都放到Rakefile中,它会很大并且很难读取/找到东西,所以我试着将每个命名空间放在lib/rake中它自己的文件中,我添加了这个到我的rake文件的顶部:Dir['#{File.dirname(__FILE__)}/lib/rake/*.rake'].map{|f|requiref}它加载文件没问题,但没有任务。我现在只有一个.rake文件作为测试,名为“servers.rake”,它看起来像这样:namespace:serverdotask:testdoputs"test"endend所以当我运行rakeserver:testid时

  8. ruby-on-rails - 在 Rails 中将文件大小字符串转换为等效千字节 - 2

    我的目标是转换表单输入,例如“100兆字节”或“1GB”,并将其转换为我可以存储在数据库中的文件大小(以千字节为单位)。目前,我有这个:defquota_convert@regex=/([0-9]+)(.*)s/@sizes=%w{kilobytemegabytegigabyte}m=self.quota.match(@regex)if@sizes.include?m[2]eval("self.quota=#{m[1]}.#{m[2]}")endend这有效,但前提是输入是倍数(“gigabytes”,而不是“gigabyte”)并且由于使用了eval看起来疯狂不安全。所以,功能正常,

  9. ruby - 使用 ruby​​ 和 savon 的 SOAP 服务 - 2

    我正在尝试使用ruby​​和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我

  10. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

随机推荐