PHP - 无法通过mysqli_stmt_send_long_data发送图像

时间:2017-04-26 19:22:45

标签: php mysql ajax

我正在创建一个日志记录系统,我希望用户可以保存他们的个人资料图像以及基本信息(名称,用户名,密码)。为此,我编写了这些文件:

HTML表单(在index.php处):

<form id='signupform' enctype="multipart/form-data">
          <table style='margin: 0px auto; border-collapse: separate; border-spacing: 0 1em; color: #ffffff;'>
            <tr>
              <th colspan='2'>
                <h2>SIGN UP</h2>
                <p>
                  Please fill out ALL the fields
                </p>
              </th>
            </tr>
            <tr>
              <td colspan='2'>
                <div id='signuperror' style='display: block; width: 100%; height: 20px; border: 2px solid #ff0000; border-radius: 10px; background-color: #ffffff; color: #ff0000; text-align: center; opacity: 0;'>Username is taken!</div>
              </td>
            </tr>
            <tr>
              <td style='text-align: right;'>
                First Name:
              </td>
              <td>
                <input id='fname' type='text' name='first' placeholder='First Name' onkeyup="checkComplete('signup');" />
              </td>
            </tr>
            <tr>
              <td style='text-align: right;'>
                Last Name:
              </td>
              <td>
                <input id='lname' type='text' name='last' placeholder='Last Name' onkeyup="checkComplete('signup');" />
              </td>
            </tr>
            <tr>
              <td colspan='2' style='text-align: center;'>
                <input id='usrimg' type='file' accept='image/*' name='userimage' style='display: none;' />
                <table style='width: 100%;'>
                  <tr>
                    <td style='width: 90%;'>
                      <button type='button' class='popbtn' onclick='browseImage();' style='width: 100%;'>Profile Image</button>
                    </td>
                    <td style='width: 10%;'>
                      <img id='imgstats' style='vertical-align: middle; display: none;' src='imgsuccess.png' />
                    </td>
                  </tr>
                </table>
              </td>
            </tr>
            <tr>
              <td style='text-align: right;'>
                Username:
              </td>
              <td>
                <input id='username' type='text' name='uid' placeholder='Username' onfocusout="checkUID(this.value);" onkeyup="checkComplete('signup');" />
              </td>
            </tr>
            <tr>
              <td style='text-align: right;'>
                Password:
              </td>
              <td>
                <input id='password' type='password' name='pwd' placeholder='Password' onkeyup="checkComplete('signup');" />
              </td>
            </tr>
            <tr>
              <td colspan='2'  style='text-align: center;'>
                <button type='button' id='signupbtn' class='popbtn' disabled='disabled'>SIGN UP</button>
              </td>
            </tr>
          </table>
        </form>

所以,css可能会有点混淆,但基本上形式如下:

<form id='signupform' enctype="multipart/form-data">
  <input id='fname' type='text' name='first' />
  <input id='lname' type='text' name='last' />
  <input id='usrimg' type='file' name='userimage' />
  <input id='username' type='text' name='uid' />
  <input id='password' type='password' name='pwd' />
  <button type='button' id='signupbtn'>SIGN UP</button>
</form>

因此signupbtn按钮在文档加载时附加了onclick事件(也在index.php;我没有全部显示,因为它与此无关):

$(function() {
      $('#signupbtn').click(function(e) {
        e.preventDefault();
        e.stopImmediatePropagation();

        $.ajax({
          type: "POST",
          url: "signup.php",
          data: $('#signupform').serialize(),
          success: function(response){
            //...
          }
        });
        return false;
      });

  //...

});

所以我使用ajax调用文件signup.php来提交表单而不刷新。然后在那个文件上:

<?php
  session_start();

  include('connect.php');

  $first = $_POST['first'];
  $last = $_POST['last'];
  $img = mysqli_real_escape_string(file_get_contents($_FILES['userimage']['tmp_name']));
  $uid = $_POST['uid'];
  $pwd = $_POST['pwd'];

  $query = "insert into Users (first, last, img, uid, pwd) values (?,?,?,?,?)";
  $stmt = mysqli_prepare($connect, $query);
  mysqli_stmt_bind_param($stmt, 'ssbss', $first, $last, $img, $uid, $pwd);
  mysqli_stmt_send_long_data($stmt, 2, $img);
  $res = mysqli_stmt_execute($stmt);

  echo $res;
?>

我从表单中检索所有信息,然后使用mysqli_stmt_send_long_data尝试将我的图像插入到在connect.php上创建的表中:

<?php
  $host_name  = "xxx";
  $database   = "xxx";
  $user_name  = "xxx";
  $password   = "xxx";


  $connect = mysqli_connect($host_name, $user_name, $password, $database);

  if(mysqli_connect_errno()) {
    echo '<p>Failed to connect to MySQL: '.mysqli_connect_error().'</p>';
  }
  else {
    //echo '<p>Connection to MySQL server successfully established.</p>';
    $db_selected = mysqli_select_db($connect, $database);

    if ($db_selected) {
      $userTableName = 'Users';

      $userTableExists = mysqli_query($connect, "select * from $userTableName");
      if (!$userTableExists) {
        echo 'The table ' . $userTableName . ' does not exist. Creating...<br /><br />';

        $sqlCreateTable = "create table " . $userTableName . "( id int(11) not null PRIMARY KEY AUTO_INCREMENT,
                                                                first varchar(128) not null,
                                                                last varchar(128) not null,
                                                                img longblob not null,
                                                                uid varchar(128) not null,
                                                                pwd varchar(1000) not null)";
        $result = mysqli_query($connect, $sqlCreateTable);

        if ($result) {
                    echo 'Table ' . $userTableName . ' created...<br>';
                }
                else {
                    die("Cannot create table " . $userTableName . ": " . mysql_error());
                }
      }
    }
    else {
            die("Cannot use " . $database . ": " . mysql_error());
        }
  }
?>

正如您所提出的那样,因为我问这个问题,Ajax会成功结束并插入行。但是当我在我网站的数据库中查看phpMyAdmin时,我发现img字段的值为[BLOB - 0 B],这只能表示图片上传无效。可能是这样的?我发现send_long_data无法正常工作,但也许有人遇到了同样的问题。感谢你提前得到任何答案。

1 个答案:

答案 0 :(得分:0)

根据Jay Blanchard的建议,我决定放弃BLOB的想法,而是保存有关图像的字符串信息。为此,我首先修改了connect.php文件以创建表的更好版本:

<?php
  $host_name  = "xxx";
  $database   = "xxx";
  $user_name  = "xxx";
  $password   = "xxx";


  $connect = mysqli_connect($host_name, $user_name, $password, $database);

  if(mysqli_connect_errno()) {
    echo '<p>Failed to connect to MySQL: '.mysqli_connect_error().'</p>';
  }
  else {
    //echo '<p>Connection to MySQL server successfully established.</p>';
    $db_selected = mysqli_select_db($connect, $database);

    if ($db_selected) {
      $userTableName = 'Users';

      $userTableExists = mysqli_query($connect, "select * from $userTableName");
      if (!$userTableExists) {
        echo 'The table ' . $userTableName . ' does not exist. Creating...<br /><br />';

        $sqlCreateTable = "create table " . $userTableName . "( id int(11) not null PRIMARY KEY AUTO_INCREMENT,
                                                                first varchar(128) not null,
                                                                last varchar(128) not null,
                                                                sex varchar(1) not null,
                                                                img varchar(5) not null,
                                                                uid varchar(128) not null,
                                                                pwd varchar(1000) not null)";
        $result = mysqli_query($connect, $sqlCreateTable);

        if ($result) {
                    echo 'Table ' . $userTableName . ' created...<br>';
                }
                else {
                    die("Cannot create table " . $userTableName . ": " . mysql_error());
                }
      }
    }
    else {
            die("Cannot use " . $database . ": " . mysql_error());
        }
  }
?>

所以现在有两个新字段:性别(1个字符可以保存&#39; m&#39; f&#39;)和img(最多5个字符可以保存图像EXTENSION)。重要的是,为了使这个表单更加完整,用户应该有机会选择自己的图像,或选择临时默认图像。这就是为什么性领域很重要以及反映形式变化的原因:

<form id='signupform' enctype="multipart/form-data">
  <input id='fname' type='text' name='first' />
  <input id='lname' type='text' name='last' />
  I am <input type='radio' name='sex' value='m' />Male <input type='radio' name='sex' value='f' />Female
  <input id='usrimg' type='file' name='userimage' />
  <input type='checkbox' id='imgdef' />Use a default image for now
  <input id='username' type='text' name='uid' />
  <input id='password' type='password' name='pwd' />
  <button type='button' id='signupbtn'>SIGN UP</button>
</form>

现在,当我按下signupbtn时,会调用两个ajax函数,具体取决于是否选中了复选框:

$(function() {
      $('#signupbtn').click(function(e) {
        e.preventDefault();
        e.stopImmediatePropagation();

        var filextension;

        if (!(document.getElementById('imgdef').checked)) {
          filextension = $('#usrimg').val().substr($('#usrimg').val().lastIndexOf('.') + 1);

          var fdata = new FormData();
          fdata.append('first', $('#fname').val());
          fdata.append('last', $('#lname').val());
          fdata.append('sex', $("#signupform input[type='radio']:checked").val());
          fdata.append('userimage', $('#usrimg').prop("files")[0]);
          fdata.append('uid', $('#username').val());
          fdata.append('pwd', $('#password').val());
          fdata.append('filextension', filextension);

          $.ajax({
            type: "POST",
            url: "uploadimage.php",
            data: fdata,
            processData: false,
            contentType: false
          });
        }
        else filextension = 'no';

        $.ajax({
          type: "POST",
          url: "signup.php",
          data: $('#signupform').serialize() + '&filextension=' + filextension,
          success: function(response) {
            //...
          }
        });
      });

      //...
}); 

如果未选中该复选框,则用户必须上传自己的图像。在这种情况下,我在ajax下创建一个FormData以进行正确上传(注意:我丢失了很多时间将signupform作为参数分配。文件永远不会以这种方式上传),然后当所有内容都被追加时,我调用了将调用uploadimage.php的ajax函数:

<?php
  include('connect.php');

  $res = mysqli_query($connect, "select count(1) from Users");
  $row = mysqli_fetch_array($res);
  $imgnum = $row[0];

  $dir = 'Users/';
  $ext = $_POST['filextension'];
  $file = $dir . 'user' . $imgnum . '.' . $ext;

  $upload = move_uploaded_file($_FILES['userimage']['tmp_name'], $file);
?>

代码比看起来简单。虽然总是建议检查文件是否是图像,如果大小是正确的,等等,我已经在javascript中这样做,所以我甚至不打扰这里。在这里,我得到了Users表的行数,这样我就能得到下一个用户。我这样做是因为我发现使用通用名称保存上传的图像更方便(在这种情况下,根据表中是否有n行,新用户的图像将保存为usern.ext,其中ext将是扩展名(jpg,png,gif等),而不是必须保留原始图像的整个字符串的名称。

如果用户选择默认值,则扩展名变为no以指示其显示。基本上,index.php中有另一个表单,用于登录,提供用户名和密码,名为signin.php的文件:

<?php
  session_start();

  include('connect.php');

  $uid = $_POST['signinuid'];
  $pwd = $_POST['signinpwd'];

  $sql = "select * from Users where uid='$uid' and pwd='$pwd'";
  $res = mysqli_query($connect, $sql);

  $row = mysqli_fetch_assoc($res);

  $_SESSION['id'] = $row['id'];
  $_SESSION['first'] = $row['first'];
  $_SESSION['last'] = $row['last'];
  $_SESSION['sex'] = $row['sex'];
  $_SESSION['img'] = $row['img'];
  $_SESSION['uid'] = $row['uid'];

  header("Location: http://....php");
?>

因此,当用户登录时,所有这些值都存储在$ _SESSION中,然后页面刷新。这样,如果用户登录,则可以显示他们的信息,而不是提示注册或登录(隐藏),以及注销按钮:

<?php
      if ($_SESSION['id']) {
        $soutid = 'signout';
        echo "<table style='margin: 0px auto;'>";
          echo "<tr>";
            echo "<td colspan='2'>";
              echo "<h1>WELCOME!</h1>";
            echo "</td>";
          echo "</tr>";
          echo "<tr>";
            echo "<td>";
              if ($_SESSION['img'] == 'no') {
                echo "<img src='Users/" . $_SESSION['sex'] . "def.png' alt=''>";
              }
              else echo "<img src='Users/user" . $_SESSION['id'] . "." . $_SESSION['img'] . "' alt=''>";
            echo "</td>";
            echo "<td>";
              echo "<div style='color: #007146; font-size: 20px; text-align: center;'>";
                echo $_SESSION['first'] . " " . $_SESSION['last'] . "(" . $_SESSION['uid'] . ")";
              echo "</div>";
            echo "</td>";
          echo "</tr>";
          echo "<tr>";
            echo "<td colspan='2'>";
              echo "<form id='$soutid' method='POST' action='signout.php'>";
                echo "<button type='button' class='popbtn'>Sign Out</a>";
              echo "</form>";
            echo "</td>";
          echo "</tr>";
        echo "</table>";
      }
    ?>

这是我的所有策划汇集在一起​​的地方,好像$_SESSION['img']no,然后我调用默认图片mdef.pngfdef.png,具体取决于用户的身份注册后选择了这条线:

echo "<img src='Users/" . $_SESSION['sex'] . "def.png' alt=''>";

并且,如果用户提供了图像,我会使用他们的ID和存储的扩展名来调用它:

echo "<img src='Users/user" . $_SESSION['id'] . "." . $_SESSION['img'] . "' alt=''>";

我没有显示我的所有代码,因为我想先完成我的表单。我没有处理过密码,确认电子邮件,密码恢复和用户个人资料页面(既可以查看未登录的用户,也可以查看用户需要编辑的内容)。完成此操作后,我会记录我的进度并在此处留下视频链接。感谢所有帮助我到这个州的人。

最后编辑:项目现已完成!您将在此处找到演示视频:https://www.youtube.com/watch?v=cLpbKdTY_xo&t=2s