【问题标题】:Php uploading a file & creating a directoryphp上传文件并创建目录
【发布时间】:2020-12-21 03:21:12
【问题描述】:

英语不是我的第一/第二语言,我不知道如何说出来,但我试着解释一下我想做什么。 我不是要求有人直接为我做这件事,而是指导我从哪里开始,截至目前我什至不知道在谷歌上搜索什么。 基本上我有一个位于共享主机上的域。主要用于测试目的,所以我并不真正关心安全性或任何此类问题,因为我的域上没有上传任何重要/敏感的内容。

所以基本上我经常必须通过 FTP 登录并创建一个新文件夹并添加一个简单的预制 index.html 文件,当我必须每天执行 10 次以上相同的任务时,它会变得很累。 所以我在想,如果我创建一个简单的用户界面,我可以简单地放入目录名称并附加 .html 文件,这样就可以完成。无需通过 FTP 登录。

这很容易吗?我只是想继续访问 domain.com/create 并拥有一个简单的 UI,您只需在其中附加 .html 文件和目录名称,然后单击“提交”。

我真的希望我写的东西有意义,因为我不知道从哪里开始。 如果你认真读到最后,谢谢。

【问题讨论】:

    标签: php html apache directory shared-hosting


    【解决方案1】:

    是的,只要您不关心安全性,这相当容易;)

    您想查看mkdirmove_uploaded_file。将目录名和文件收集到一个表格中,创建目录,将上传的文件移到那里。我链接到的文档中的示例代码应该足以让它工作。

    [编辑] 这是一个如何以某种安全的方式执行此操作的示例。这是最简单的。免责声明 - 允许将文件上传到您的 Web 根目录是危险的。我不负责是否有人拥有您的服务器!

    <?php
    //Set up variables we will need later
    $directoryName = '';
    $status        = 'init';
    $errorMessage  = '';
    
    //A super secret password that is required in order to do the dangerous things
    $password = 'secret!';
    
    //If submit is in the post (result of the submit button being pressed)
    if (array_key_exists('submit', $_POST))
    {
        try
        {
            //Get the directory name input first so we can set it back in the field if the login fails
            $directoryName = $_POST['directory_name'];
    
            //First verify the password
            $passwordEntry = $_POST['password'];
            if ($passwordEntry != $password)
            {
                throw new Exception('Authentication error');
            }
    
            //If the directory name is blank, bail out
            if (empty($directoryName))
            {
                throw new Exception('Directory name is required');
            }
    
            //Make sure nobody can traverse from the root of the filesystem
            if (substr($directoryName, 0, 1) == '/')
            {
                $directoryName = substr($directoryName, 1);
            }
    
            /*
             * Get rid of slashes and anything after them. After this, if someone entered
             * "/etc/passwd", we would have "etc"
             */
            $directoryName = preg_replace('/\/(.*)?/', '', $directoryName);
    
            //If the directory already exists, bail out
            if (file_exists($directoryName))
            {
                throw new Exception('Directory already exists');
            }
    
            //Make sure we have a file in the request. If not, bail out.
            if (empty($_FILES["index_file"]["tmp_name"]))
            {
                throw new Exception('Please upload a file');
            }
    
            //Create our directory
            mkdir($directoryName);
    
            //Get the temporary path to the file - this is where the server stashed it
            $tmpName = $_FILES["index_file"]["tmp_name"];
    
            //Create a path to where we want the file
            $destinationPath = $directoryName . '/index.html';
    
            //Attempt to move the file, this return true on success, false on failure
            $fileMoveStatus = move_uploaded_file($tmpName, $destinationPath);
    
            //If the file could not be moved, remove the directory we created an bail out
            if ($fileMoveStatus === false)
            {
                rmdir($directoryName);
                throw new Exception('Unable to move file to destination');
            }
    
            //Change the permissions on the HTML file so nobody can monkey with it
            chmod($directoryName . '/index.html', 0644);
    
            /*
             * Reset the directory name - we put this variable in the field so the user
             * won't have to re-type it if an error occurs. We want it to be empty now
             * that the process was successful
             */
            $directoryName = '';
    
            // Set the status to success so we display the success alert to the user
            $status = 'success';
        }
        catch (Exception $e)
        {
            // Set the status to error so we display the error alert to the user
            $status = 'error';
    
            // Set the error message to the message from the exception
            $errorMessage = $e->getMessage();
        }
    }
    ?>
    <!DOCTYPE HTML>
    <html lang="en">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
        <title>Directory Manager</title>
        <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
              integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
    </head>
    <body>
    <div class="container">
        <h1>Directory Manager</h1>
        <form method="post" enctype="multipart/form-data">
            <?php
            if ($status == 'error')
            {
                ?>
                <div class="alert alert-danger" role="alert">
                    <?php echo $errorMessage; ?>
                </div>
                <?php
            }
            elseif ($status == 'success')
            {
                ?>
                <div class="alert alert-success" role="alert">
                    File uploaded successfully<br>
                    <a href="<?php echo $destinationPath; ?>">Go to file</a>
                </div>
                <?php
            }
            ?>
            <div class="row">
                <div class="col-md-6">
                    <div class="form-group">
                        <label for="directory_name">Directory Name</label>
                        <input type="text" class="form-control" name="directory_name" id="directory_name" aria-describedby="directory_name_help" value="<?php echo $directoryName ?>">
                        <small id="directory_name_help" class="form-text text-muted">Name of directory to be
                            created.</small>
                    </div>
                </div>
                <div class="col-md-6">
                    <div class="form-group">
                        <label for="directory_name">HTML File</label>
                        <input type="file" class="form-control" name="index_file" id="index_file" aria-describedby="file_help">
                        <small id="file_help" class="form-text text-muted">index.html file</small>
                    </div>
                </div>
            </div>
            <div class="row">
                <div class="col-md-6">
                    <div class="form-group">
                        <label for="password">Password</label>
                        <input type="password" class="form-control" name="password" id="password">
                    </div>
                </div>
            </div>
            <div class="row">
                <div class="col-md-12">
                    <div class="form-group">
                        <button type="submit" name="submit" class="btn btn-primary">Submit</button>
                    </div>
                </div>
            </div>
    </div>
    </body>
    </html>
    

    [编辑 2] 复制模板文件而不是上传的版本。

    <?php
    //Set up variables we will need later
    $directoryName = '';
    $status        = 'init';
    $errorMessage  = '';
    
    //A super secret password that is required in order to do the dangerous things
    $password = 'secret!';
    
    // Path to the template file that will be copied into created directories
    $sourcePath = 'template.html';
    
    //If submit is in the post (result of the submit button being pressed)
    if (array_key_exists('submit', $_POST))
    {
        try
        {
            //Get the directory name input first so we can set it back in the field if the login fails
            $directoryName = $_POST['directory_name'];
    
            //First verify the password
            $passwordEntry = $_POST['password'];
            if ($passwordEntry != $password)
            {
                throw new Exception('Authentication error');
            }
    
            //If the directory name is blank, bail out
            if (empty($directoryName))
            {
                throw new Exception('Directory name is required');
            }
    
            //Make sure nobody can traverse from the root of the filesystem
            if (substr($directoryName, 0, 1) == '/')
            {
                $directoryName = substr($directoryName, 1);
            }
    
            /*
             * Get rid of slashes and anything after them. After this, if someone entered
             * "/etc/passwd", we would have "etc"
             */
            $directoryName = preg_replace('/\/(.*)?/', '', $directoryName);
    
            //If the directory already exists, bail out
            if (file_exists($directoryName))
            {
                throw new Exception('Directory already exists');
            }
    
            //Create our directory
            mkdir($directoryName);
    
            //Create a path to where we want the file
            $destinationPath = $directoryName . '/index.html';
    
            //Attempt to copy the file, this return true on success, false on failure
            $fileCopyStatus = copy($sourcePath, $destinationPath);
    
            //If the file could not be copied, remove the directory we created an bail out
            if ($fileCopyStatus === false)
            {
                rmdir($directoryName);
                throw new Exception('Unable to copy template file to destination');
            }
    
            //Change the permissions on the HTML file so nobody can monkey with it
            chmod($directoryName . '/index.html', 0644);
    
            /*
             * Reset the directory name - we put this variable in the field so the user
             * won't have to re-type it if an error occurs. We want it to be empty now
             * that the process was successful
             */
            $directoryName = '';
    
            // Set the status to success so we display the success alert to the user
            $status = 'success';
        }
        catch (Exception $e)
        {
            // Set the status to error so we display the error alert to the user
            $status = 'error';
    
            // Set the error message to the message from the exception
            $errorMessage = $e->getMessage();
        }
    }
    ?>
    <!DOCTYPE HTML>
    <html lang="en">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
        <title>Directory Manager</title>
        <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
              integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
    </head>
    <body>
    <div class="container">
        <h1>Directory Manager</h1>
        <form method="post" enctype="multipart/form-data">
            <?php
            if ($status == 'error')
            {
                ?>
                <div class="alert alert-danger" role="alert">
                    <?php echo $errorMessage; ?>
                </div>
                <?php
            }
            elseif ($status == 'success')
            {
                ?>
                <div class="alert alert-success" role="alert">
                    File uploaded successfully<br>
                    <a href="<?php echo $destinationPath; ?>">Go to file</a>
                </div>
                <?php
            }
            ?>
            <div class="row">
                <div class="col-md-6">
                    <div class="form-group">
                        <label for="directory_name">Directory Name</label>
                        <input type="text" class="form-control" name="directory_name" id="directory_name" aria-describedby="directory_name_help" value="<?php echo $directoryName ?>">
                        <small id="directory_name_help" class="form-text text-muted">Name of directory to be
                            created.</small>
                    </div>
                </div>
                <div class="col-md-6">
                    <div class="form-group">
                        <label for="password">Password</label>
                        <input type="password" class="form-control" name="password" id="password">
                    </div>
                </div>
            </div>
            <div class="row">
                <div class="col-md-12">
                    <div class="form-group">
                        <button type="submit" name="submit" class="btn btn-primary">Submit</button>
                    </div>
                </div>
            </div>
    </div>
    </body>
    </html>
    

    【讨论】:

    • 非常感谢,我不太了解有关如何收集目录名称或使其工作的示例,但至少我知道我必须做什么.谢谢!
    • 不客气 - 我添加了一个包含一些基本安全预防措施的工作示例。
    • 快速提问,有没有办法传输已经在我的网络服务器中的 index.html 文件并完全跳过上传部分?正在上传的文件始终相同。再次非常感谢你。这看起来比我做的任何东西都要好。
    • 当然,我添加了一个可以做到这一点的版本。只需更改 $sourcePath 变量以指向要复制到新目录中的文件。你可以这样做!只需花一些时间弄清楚所有部分都在做什么。