您的位置:

PHP实现文件上传

一、上传文件实现基础

文件上传是网站开发中常用的功能之一,通过上传文件可以实现一些交互式的操作,如用户头像,文件分享,图片上传等。在PHP中,通过$_FILES超全局变量可以实现文件上传功能。该变量是一个数组,包含上传文件的各种信息,如文件名,文件类型,文件临时存储路径等。



   
<input type="file" name="file" id="file"> <input type="submit" value="上传" name="submit">

如上所示,通过HTML表单中添加type="file"的input标签,用户可以选择本地文件进行上传。在form表单中设置enctype="multipart/form-data",告诉服务器该表单中包含二进制数据,而非普通字符数据。在表单提交后,可以通过isset函数判断是否选择了文件,然后通过$_FILES['file']获取上传文件的信息。将文件从临时目录移动到指定的目录,就可以完成文件上传操作。


if (isset($_POST["submit"]) && isset($_FILES["file"])) {
    $file = $_FILES["file"];
    if ($file["error"] === UPLOAD_ERR_OK) {
        $name = $file["name"]; // 上传文件的文件名
        $type = $file["type"]; // 文件类型
        $tmp_name = $file["tmp_name"]; // 文件被上传到服务器上的临时文件名
        $size = $file["size"]; // 文件大小
        $upload_dir = "/var/www/upload/"; // 上传目录
        if (!is_dir($upload_dir)) {
            mkdir($upload_dir, 0777, true);
        }
        $dest = $upload_dir . $name;
        move_uploaded_file($tmp_name, $dest);
        echo "上传成功";
    } else {
        echo "上传失败";
    }
}

二、文件上传的安全性问题

在实现文件上传功能时,应该考虑到其中的安全性问题,防止出现文件被上传到服务器后,被误用或成为安全漏洞的情况。

1、文件类型检查

用户上传的文件类型由浏览器来检测,但是有时候浏览器并不能完全判断文件类型,很容易被伪装成其他文件类型,导致安全隐患。因此,在服务器端对上传文件的MIME类型进行检查是很必要的。可以通过使用PHP提供的finfo_file函数来获取上传文件的MIME类型。


$fileinfo = finfo_open(FILEINFO_MIME_TYPE);
$type = finfo_file($fileinfo, $tmp_name);
if ($type !== "image/png") {
    echo "不支持的文件类型";
    exit;
}

2、文件大小限制

为了防止用户上传过大的文件,导致服务器资源消耗过度,应该对上传文件大小进行限制,一般情况下文件大小不应该超过2MB。可以通过设置php.ini或使用ini_set函数来修改文件大小限制。


ini_set("upload_max_filesize", "2M"); // 上传文件的最大尺寸为2MB
ini_set("post_max_size", "2M"); // POST请求的最大尺寸为2MB

3、文件名检查

用户上传的文件名可能含有特殊字符,如空格、斜杠等,容易造成路径穿越攻击,应该对文件名进行过滤和检查。可以使用preg_match函数和正则表达式对文件名进行校验。


if (!preg_match('/^[a-zA-Z0-9]+[a-zA-Z0-9\._-]*$/', $name)) {
    echo "非法的文件名";
    exit;
}

三、文件上传进度显示

在文件上传过程中,如果上传的文件过大,可能需要一些时间才能完成上传,为了更好的用户体验,可以在上传过程中显示上传进度。



   
<input type="file" name="file" id="file"> <input type="submit" value="上传" name="submit">
<script> var form = document.querySelector("form"); form.addEventListener("submit", function(e) { e.preventDefault(); var file_input = document.getElementById("file"); var file = file_input.files[0]; var xhr = new XMLHttpRequest(); xhr.open("POST", "upload.php"); xhr.upload.onprogress = function(e) { if (e.lengthComputable) { var progress = document.getElementById("progress"); progress.style.display = "block"; var percent = Math.round(e.loaded / e.total * 100); var progress_bar = progress.querySelector(".progress-bar"); progress_bar.style.width = percent + "%"; progress_bar.setAttribute("aria-valuenow", percent); progress_bar.innerHTML = percent + "%"; } }; xhr.onload = function() { alert(xhr.responseText); var progress = document.getElementById("progress"); progress.style.display = "none"; }; var form_data = new FormData(); form_data.append("file", file); xhr.send(form_data); }); </script>

上述代码通过XMLHttpRequest对象实现异步上传文件,并通过事件监听onprogress实现上传进度显示,在上传完成后将进度条隐藏。