如何创建上传文件的表单并将其名称设置为带变量的串联字符串?

时间:2019-07-19 23:57:16

标签: php html

我正在学习一些PHP,并试图创建一个表单来更新图像并将其名称设置为"img".$_POST['something']."jpg",但是结果始终是img.jpg

我知道$_POST['something']有一个值,因为我正在使用它在同一页面中运行查询。

我花了一整天(今天)试图弄清楚这一点,但是到目前为止我已经没有想法了。请帮忙。

我使用msqli_fetch_array的方式可能有问题(我说是由于警告),我试图进行更改,但不确定如何。

在代码中产生了很多回声之后,我发现当我单击提交时,页面的一部分会重新加载新的$_POST变量,这就是为什么我的postedId消失在这一点..这有意义吗?我该如何解决?

<?php
  /* Displays user information and some useful messages */
  require 'db.php';
  session_start();

  // Check if user is logged in using the session variable
  if ($_SESSION['logged_in'] != 1) {
    $_SESSION['message'] = "You must log in before viewing your profile page!";
    header("location: error.php");  
  }

  $postedId = $_POST['stid'];

  $result = mysqli_query($mysqli, "SELECT stcontents.id, `st_id`, `name` FROM `students`, `stcontents` WHERE stcontents.tc_id = ".$_SESSION['tcid']." AND students.id = st_id AND st_id = ".$postedId." GROUP BY st_id");

  $row = mysqli_fetch_array($result);
?>

<!doctype html>
<html lang="en">
  <body>
    <div class="container" id="turma-container">
      <form action="" method="post" enctype="multipart/form-data">
        <p>Image:</p>
        <input type="file" name="fileToUpload" id="fileToUpload">
        <input type="submit" value="Upload Image" name="submit">
      </form>
      <?php
        $target_dir = "resources/images/";
        $target_file = $target_dir."img".$postedId.".jpg";
        $uploadOk = 1;
        $imageFileType = strtolower(pathinfo($target_file,PATHINFO_EXTENSION));
        // Check if image file is a actual image or fake image
        if(isset($_POST["submit"])) {
          $check = getimagesize($_FILES["fileToUpload"]["tmp_name"]);
          if($check !== false) {
            echo "File is an image - " . $check["mime"] . ".";
            $uploadOk = 1;
          } else {
            echo "File is not an image.";
            $uploadOk = 0;
          }
        }
        // Check file size
        if ($_FILES["fileToUpload"]["size"] > 500000) {
          echo "Sorry, your file is too large.";
          $uploadOk = 0;
        }
        // Allow certain file formats
        if($imageFileType != "jpg") {
          echo "Sorry, only JPG files are allowed.";
          $uploadOk = 0;
        }
        // Check if $uploadOk is set to 0 by an error
        if ($uploadOk == 0) {
          echo "Sorry, your file was not uploaded.";
        // if everything is ok, try to upload file
        } else {
          if (move_uploaded_file($_FILES["fileToUpload"]["tmp_name"], $target_file)) {
          echo "The file ". basename( $_FILES["fileToUpload"]["name"]). " has been uploaded.";
          } else {
            echo "Sorry, there was an error uploading your file.";
          }
        }
      ?>
    </div>
  </body>
</html>

我期望生成的文件名类似于img6.jpg,而不是img.jpg。这是我得到的日志

  

[2019年7月19日23:41:27 UTC] PHP注意:未定义的索引:fileToUpload   在第46行的/home/[...]/myfolder/myfile.php中[2019年7月19日23:41:27   [UTC] PHP注意:未定义的索引:fileToUpload   /home/[...]/myfolder/myfile.php,第60行[19-Jul-2019 23:41:33 UTC]   PHP注意:未定义的索引:固定在/home/[...]/myfolder/myfile.php中   在线12 [19-Jul-2019 23:41:33 UTC] PHP警告:   mysqli_fetch_array()期望参数1为mysqli_result,布尔   在第16行的/home/[...]/myfolder/myfile.php中给出

2 个答案:

答案 0 :(得分:0)

首先,我要感谢向我发送提示并花时间阅读我的代码的每个人。我进行了更改,但仍无法按预期进行。

正如我所说,借助ArendE的技巧,我在代码中进行了很多更改,现在我认为它变得更加有意义(我认为我也可以更好地理解它)。 我要更改的一件事是使它更加完整,不仅可以选择上传图像,还可以添加/更改文本并查看图像(如果图像已经上传)。 不幸的是,某些东西仍然无法正常工作。发布代码时,我会尽力解释。

每个id变量都是一个int,初始$ _POST来自另一个页面中的按钮。

顶级php,在这里建立连接并声明一些变量:

<?php
/* Displays user information and some useful messages */
session_start();
require 'db.php';

// Check if user is logged in using the session variable
if (empty($_SESSION['logged_in'] != 1) {
    $_SESSION['message'] = "You must log in before viewing your profile page!";
    header("location: error.php");
    exit();
}
else {
    // Makes it easier to read
    $name = $_SESSION['name'];
}

if (isset($_POST['stid'])) {
    $pstid = $_POST['stid'];
    $result = mysqli_query($link, "SELECT `id`, `tc_id`, `name`, `essay`, `image` FROM `students` WHERE tc_id = ".$tcid." AND id = ".$pstid.";");
    $row = mysqli_fetch_array($result);

    $stname = $row['name'];
    $cessay = $row['essay'];
    $cimage = $row['image'];
}
?>

一些html,我在这里创建文本字段(如果数据库中有文本,则已经包含文本),显示图像(如果仍然存在),并提供一个上载图像选项来更改/添加它。如果用户更改了文字或图像,则会单击“保存”按钮。

<form method="post" enctype="multipart/form-data">
    <div class="form-group">
        <label for="TextToUpload">Text:</label>
        <textarea type="text" class="form-control" id="TextToUpload" rows="5" name="stessay"><?php echo $cessay; ?></textarea>
    </div>

    <p>Imagem do(a) aluno(a):</p>
    <?php
        if (isset($row['image'])) {
            echo "<img src=\"resources/images/studentsImages/".$cimage."\">";
        }

        echo "<input type=\"hidden\" name=\"stid\" value=".$pstid.">";
    ?>
    <input type="file" name="fileToUpload" id="fileToUpload">
    <input formmethod="post" type="submit" value="savechanges" name="submit">
</form>

和底部php。在这里,我检查是否有文本和/或是否选择了要更新的文件。进行了一些检查,好像文件已损坏,我尝试将它们都发送出去。

<?php
    if(isset($_POST["submit"])) {
        $essayOk = 0;
        $imageOk = 0;

        if(isset($_POST['stessay'])) {
            $essayOk = 1;
            $pessayc = mysqli_real_escape_string($link, $_POST['stessay']);
        }

        if (isset($_POST['fileToUpload'])) {
            $target_dir = "resources/images/";
            $target_file = $target_dir."img".$pstid.".jpg";

            $imageFileType = strtolower(pathinfo($target_file,PATHINFO_EXTENSION));
            // Check if image file is a actual image or fake image
            if($mime = finfo_file($finfo, $target_dir . $_FILES["fileToUpload"]["tmp_name"])) {
                if($mime == 'image/jpg' || $mime == 'image/jpeg') {
                    if(getimagesize($target_dir . $_FILES["fileToUpload"]["tmp_name"]) === false) {
                        echo "File is corrupt";
                        $uploadOk = 0;
                    } else {
                        echo "File is an image - " . $mime . ".";
                        $uploadOk = 1;
                    }                           
                } else {
                    echo $mime . " is not supported.";
                    $uploadOk = 0;
                }
            } else {
                echo "Invalid file";
                $uploadOk = 0;
            }
            // Check file size
            if ($_FILES["fileToUpload"]["size"] > 500000) {
                echo "The file is too big.";
                $imageOk = 0;
            }
            // Check if $imageOk is set to 0 by an error
            if ($imageOk == 0) {
                echo "Erros sending image, try again later.";
            // if everything is ok, try to upload file
            }
        }

        if ($essayOk == 1) {
            $query = "UPDATE students SET essay = '".$pessayc."' WHERE id = '".$pstid."';";
            if (mysqli_query($link, $query)) {
                echo "<p>Essay updated!</p>";
            } else {
                printf("Errormessage: %s\n", mysqli_error($link));
                echo "<p>There was an error updating the ssay, try again later.</p>";
            }
        }

        if ($imageOk == 1) {
            if (move_uploaded_file($_FILES["fileToUpload"]["tmp_name"], $target_file)) {
                echo "The file ".basename($_FILES["fileToUpload"]["name"])." was updated.";
            } else {
                echo "Your image was not updated, try again later.";
            }
        }
    }    
?>

我认为问题出在代码的底部php部分,由于某种原因(我不知道),好像isset($ _ POST ['fileToUpload'])每次都返回false,即使选择了文件。 ir不应该随身携带,stid和提交吗?这次,error_log上绝对没有任何内容。 $ _POST的print_r仅返回Array([stessay] => Test [stid] => 1 [submit] => savechanges) 为什么还没有fileToUpload?

答案 1 :(得分:-1)

您已经花了一整天的时间了,让我给您提供一些建议。我希望您可以从中学到一些东西,并理解为什么那些“未定义”和“通知”在那里。我尚未测试代码,但是如果您浏览所有注释,希望您能理解并能够使它开始工作。

<?php
    // Always start sessions first:
    // if your db.php throws an error, the session can't start anymore
    // and throws a warning
    session_start(); 

    require('db.php');

    // Do check if a variable exists. PHP should throw you a warning otherwise.

    if(empty($_SESSION['logged_in']) || $_SESSION['logged_in'] != 1) {
        $_SESSION['message'] = "You must log in before viewing your profile page!";
        header("Location: error.php");

        // Stop running the script after a redirect! 
        // A header is an instruction, a client 
        // might simple ignore it and show the page content anyway
        exit();
    }

    // Check if the variable exists!
    // Long way:
    // if(isset($_POST['stid'])) { $postedId = $_POST['stid'] } else { $postedId = false; }
    // Medium way:
    // $postedId = (isset($_POST['stid']) ? $_POST['stid'] : false;
    // Short way:
    $postedId = $_POST['stid']?:false;

    // Make your query look nice, makes your life easy and debugging too
    // Query questions: 
    // 1. What if $_SESSION['tcid'] doesn't exist?
    // 2. What if $postedId doesn't exist?
    // 3. What if $postedId is 0; DROP TABLE students; ?
    // Remember, a client can send anything via $_POST['stid']
    //
    //$qry = "SELECT stcontents.id, `st_id`, `name` 
    //      FROM `students`, `stcontents` 
    //      WHERE stcontents.tc_id = " . $_SESSION['tcid'] . " 
    //      AND students.id = st_id 
    //      AND st_id = " . $postedId . " GROUP BY st_id";
    //
    // Read about mysqli_real_escape_string
    // https://www.php.net/manual/en/mysqli.real-escape-string.php
    // Want to do it really right? Use prepared statements
    // https://www.php.net/manual/en/mysqli.prepare.php

    $qry = "SELECT stcontents.id, `st_id`, `name` 
            FROM `students`, `stcontents` 
            WHERE stcontents.tc_id = " . mysqli_real_escape_string($mysqli, $_SESSION['tcid']) . " 
            AND students.id = st_id 
            AND st_id = " . mysqli_real_escape_string($mysqli, $postedId) . " GROUP BY st_id";

    $result = mysqli_query($mysqli, $qry);
    $row = mysqli_fetch_array($result);

    // But what if no result was found?
    if(empty($postedId) || empty($row)) {
        exit('Something above went wrong!');
    }
?>
<!doctype html>
<html lang="en">
    <body>
        <div class="container" id="turma-container">
            <!-- 
            // Leave out the action if it's empty anyway
            // https://stackoverflow.com/questions/1131781/is-it-a-good-practice-to-use-an-empty-url-for-a-html-forms-action-attribute-a
            -->
            <form method="post" enctype="multipart/form-data">
                <p>Image:</p>
                <input type="file" name="fileToUpload" id="fileToUpload">
                <input type="submit" value="Upload Image" name="submit">
            </form>

            <?php
                $target_dir = "resources/images/"; // Better use the full path

                // $target_file = $target_dir."img".$postedId.".jpg";
                // What if $postedId is /../../logo ?
                // Is resources/images/img/../../logo.jpg a valid path?             
                //
                // I'll assume $postedId will be an integer (number)
                // using https://www.php.net/manual/en/function.settype.php

                settype($postedId, 'int');

                // Another approach: basename()
                // https://www.php.net/manual/en/function.basename.php
                // https://www.php.net/manual/en/features.file-upload.post-method.php

                $target_file = $target_dir . basename("img" . $postedId . ".jpg");
                $uploadOk = 1;

                // $imageFileType = strtolower(pathinfo($target_file,PATHINFO_EXTENSION));
                // You have just made a string $target_file.. so
                // nothing is there, or it would be jpg anyway, since you've said ".jpg"

                if(isset($_POST["submit"])) {

                    // So $_POST['submit'] might be there, but was the fileToUpload too?

                    if(empty($_FILES["fileToUpload"])) {
                        exit('no file!');
                    }

                    // $check = getimagesize($_FILES["fileToUpload"]["tmp_name"]);
                    //
                    // Well although getimagesize indeed does return false on failure,
                    // read the caution "Do not use to check that a given file is a valid image."
                    // here https://www.php.net/manual/en/function.getimagesize.php
                    // the path it also incomplete ($target_dir is missing)

                    $finfo = finfo_open(FILEINFO_MIME_TYPE);

                    if($mime = finfo_file($finfo, $_FILES["fileToUpload"]["tmp_name"])) {
                        if($mime == 'image/jpg' || $mime == 'image/jpeg') {

                            // Now you could use getimagesize as extra check
                            // But there might be better alternatives
                            if(getimagesize($_FILES["fileToUpload"]["tmp_name"]) === false) {
                                echo "File is corrupt";
                                $uploadOk = 0;
                            } else {                        
                                echo "File is an image - " . $mime . ".";
                                $uploadOk = 1;
                            }                           
                        } else {
                            echo $mime . " is not supported.";
                            $uploadOk = 0;
                        }                       
                    } else {
                        echo "Invalid file";
                        $uploadOk = 0;
                    }               

                    if($_FILES["fileToUpload"]["size"] > 500000) {
                        echo "Sorry, your file is too large.";
                        $uploadOk = 0;
                    }


                    // if($imageFileType != "jpg") {
                    //  echo "Sorry, only JPG files are allowed.";
                    //  $uploadOk = 0;
                    // }
                    //
                    // Done this above.
                    // If the idea is some pre-flight check, consider $_FILES['fileToUpload']['type'] 

                    if($uploadOk == 0) {
                        echo "Sorry, your file was not uploaded.";
                    } else {
                        if(move_uploaded_file($_FILES["fileToUpload"]["tmp_name"], $target_file)) {
                            echo "The file ". basename($_FILES["fileToUpload"]["name"]). " has been uploaded.";
                        } else {
                            echo "Sorry, there was an error uploading your file.";
                        }
                    }
                }
            ?>
        </div>
    </body>
</html>

仍然可以进行很多优化,但这应该可以帮助您。祝你好运!如果您有任何疑问,请随时发表评论。


发表评论后,让我们开始新一轮! 再次是下面的代码:

<?php
session_start();
require 'db.php';

// So empty($var) returns true/false based on if a variable exists (isset()) and it's value 
// Read: https://www.php.net/empty what is considered FALSE is it exists
// I'm guessing this will do:
if (empty($_SESSION['logged_in'])) {
    $_SESSION['message'] = "You must log in before viewing your profile page!";
    header("location: error.php");
    exit();
} else {

    // If you are sure $_SESSION['name'] exists if a user is logged in, this is fine.
    // Otherwise consider  $name = $_SESSION['name']?:'unknown';
    $name = $_SESSION['name'];
}

if (isset($_POST['stid'])) {

    // So you still allow a raw POST variable in your database query..
    // Don't do that or you might find someone messed around with your database.
    // https://www.w3schools.com/sql/sql_injection.asp
    // $pstid = $_POST['stid'];

    $pstid = mysqli_real_escape_string($link, $_POST['stid']);
    $tcid = mysqli_real_escape_string($link, $tcid); // Where does $tcid come from? Does it exist?

    // Check if the query is succesful and if there are results..
    // In the function documentation always peek at the Parameters and Return Values
    // https://php.net/manual/en/mysqli.query.php : Returns FALSE on failure.
    // https://www.php.net/manual/en/mysqli-result.fetch-array.php : Returns NULL if there are no more rows

    if($result = mysqli_query($link, "SELECT `id`, `tc_id`, `name`, `essay`, `image` FROM `students` WHERE tc_id = ".$tcid." AND id = ".$pstid.";")) {
        if($row = mysqli_fetch_array($result)) {
            $stname = $row['name'];
            $cessay = $row['essay'];
            $cimage = $row['image'];
        } else {
            $_SESSION['message'] = "No essay was found, please create one first.";
            header("location: error.php");
            exit();
        }
    } else {
        $_SESSION['message'] = "Something went wrong..";
        header("location: error.php");
        exit();
    }

    // What if $_POST['stid'] does not exist though?
    // You use it as hidden input for your form, so let's throw an error.
} else {
    $_SESSION['message'] = "Student id not found.";
    header("location: error.php");
    exit();
}
?>

<form method="post" enctype="multipart/form-data">
    <div class="form-group">
        <label for="TextToUpload">Text:</label>

<!--
So, $cessay comes from your database; but how does it get entered? By students?
Imagine a students enters "</textarea><img src="https://i.imgur.com/BBcy6Wc.jpg">"
Right.. a cat picture will be shown.. Solution: Escape it.
https://www.w3schools.com/php/func_string_htmlspecialchars.asp
So:
--> 
        <textarea type="text" class="form-control" id="TextToUpload" rows="5" name="stessay"><?php echo $cessay; ?></textarea>
    </div>

    <p>Imagem do(a) aluno(a):</p>
    <?php
        if (isset($row['image'])) {
            // Same applies here, although cimage might be under your control, so less critical
            // Just make it a habbit to escape and you'll never have trouble :)

            $cimage = htmlspecialchars($string, ENT_QUOTES, 'UTF-8');
            echo "<img src=\"resources/images/studentsImages/".$cimage."\">";
        }

        // So I've used it before in mysqli_real_escape_string, so it now could be something like '123' instead of 123
        // Since we now need to escape it not for SQL but HTML, just use the original value again:

        echo "<input type=\"hidden\" name=\"stid\" value=".htmlspecialchars($_POST['stid'], ENT_QUOTES, 'UTF-8').">";
    ?>
    <input type="file" name="fileToUpload" id="fileToUpload">
    <input formmethod="post" type="submit" value="savechanges" name="submit">
</form>

<?php
    if(isset($_POST["submit"])) {
        $essayOk = 0;
        $imageOk = 0;

        if(isset($_POST['stessay'])) {
            $essayOk = 1;
            $pessayc = mysqli_real_escape_string($link, $_POST['stessay']); 
            // Very good! :)
        }

        // Uploaded files should be in the $_FILES array! So don't use $_POST
        if (isset($_FILES['fileToUpload'])) {
            $target_dir = "resources/images/";
            $target_file = $target_dir."img".$pstid.".jpg";

            // $imageFileType = strtolower(pathinfo($target_file,PATHINFO_EXTENSION)); // Not needed, fails anyway      
            // But where is $finfo ? The code below will always fail without it..
            // Adding it back:
            $finfo = finfo_open(FILEINFO_MIME_TYPE);        

            if($mime = finfo_file($finfo, $_FILES["fileToUpload"]["tmp_name"])) {
                if($mime == 'image/jpg' || $mime == 'image/jpeg') {
                    if(getimagesize($_FILES["fileToUpload"]["tmp_name"]) === false) {
                        echo "File is corrupt";
                        $uploadOk = 0;
                    } else {
                        echo "File is an image - " . $mime . ".";
                        $uploadOk = 1;
                    }                           
                } else {
                    echo $mime . " is not supported.";
                    $uploadOk = 0;
                }
            } else {
                echo "Invalid file";
                $uploadOk = 0;
            }

            if ($_FILES["fileToUpload"]["size"] > 500000) {
                echo "The file is too big.";
                $imageOk = 0;
            }

            if ($imageOk == 0) {
                echo "Erros sending image, try again later.";
            }
        }

        if ($essayOk == 1) {
            $query = "UPDATE students SET essay = '".$pessayc."' WHERE id = '".$pstid."';";
            if (mysqli_query($link, $query)) {
                echo "<p>Essay updated!</p>";
            } else {
                printf("Errormessage: %s\n", mysqli_error($link));
                echo "<p>There was an error updating the ssay, try again later.</p>";
            }
        }

        if ($imageOk == 1) {
            if (move_uploaded_file($_FILES["fileToUpload"]["tmp_name"], $target_file)) {
                echo "The file ".basename($_FILES["fileToUpload"]["name"])." was updated.";
            } else {
                echo "Your image was not updated, try again later.";
            }
        }
    }    
?>

关于您的最后一个问题,请检查它是否存在于$_FILES数组中,但我也相信文件名仍应位于$_POST数组中。虽然不确定。将其添加到代码顶部,以查看找到了哪些变量:

print_r($_POST);
print_r($_FILES);

它将为您提供一个不错的POST字段和上传文件列表。