首页 > 解决方案 > PHP 文件上传错误 (UPLOAD_ERR_PARTIAL) / $_FILES 为空或有空“tmp_name”

问题描述

我有一个很常见的问题,花了几个小时阅读一些关于它的东西,但我无法解决它,我快疯了......

语境

我有一个网站,用户可以在其中将图片上传到我的服务器(通常是从 iOS / Safari 浏览器)。上传表单的页面就是这个

后端是用 PHP(无框架)制作的。前端是 HTML / Javascript。这是我在 2010 年制作的一个相当古老的网站,所以这不是“超级性感”!:-)

我制作了日志来监控上传结果,我发现大约 30% 的用户上传失败了……我想这不常见!

这些错误来自 2 个来源(尝试上传多次的同一用户可能同时具有这 2 个来源):

这些错误似乎不是确定性的......


代码

上传文件的表单HTML (限制用户从客户端上传到35M)

    <ul class="pageitem">
        <form name="empty-custom-native" 
              enctype="multipart/form-data" 
              action="/upload.php?method=nativeUpload" 
              method="post">
            <input type="hidden" name="MAX_FILE_SIZE" value="36700160" />
            <li class="button" >
                <input type="file" name="iosImageFILE" id="iosImageFILE"/>
            </li>
        </form>
        <li class="button directUrlButton" onclick="javascript:onclickNativeUploadForm();">
            <input type="button" value="Upload" />
        </li>
    </ul>

HTML调用的Javascript (用于在提交表单之前检查文件输入是否为空)

  function onclickNativeUploadForm(){
    if( document.getElementById('iosImageFILE').value=="" ){
      alert("Please choose an image FIRST !");
    } else{
      showPleaseWait();
      setTimeout(submitNativeUploadForm, 2000);
    }
  }

  function submitNativeUploadForm(){
      document.forms['empty-custom-native'].submit();
  }

管理文件上传的 PHP 代码(提取)

<?php
if( isset($_FILES['iosImageFILE']) && !empty($_FILES['iosImageFILE']) ){
    $uploadStatus = $_FILES['iosImageFILE']['error'];
    if( $uploadStatus==0 ){
        // Copy source file to temp file
        if( !move_uploaded_file($_FILES['iosImageFILE']['tmp_name'], $_SERVER['DOCUMENT_ROOT']."/".$userImageTemp) ) {
            throw new Exception("fileUploadCopy");
        }

    } else{
        if( $uploadStatus==1 ){ throw new Exception("fileUploadIniSize"); }
        else if( $uploadStatus==2 ){ throw new Exception("fileUploadFormSize"); }
        else if( $uploadStatus==3 ){ throw new Exception("fileUploadPartial"); } // THIS ERROR ...
        else if( $uploadStatus==4 ){ throw new Exception("fileUploadNoFile"); }
        else if( $uploadStatus==6 ){ throw new Exception("fileUploadNoTmpDir"); }
        else if( $uploadStatus==7 ){ throw new Exception("fileUploadCantWrite"); }
        else if( $uploadStatus==8 ){ throw new Exception("fileUploadExtension"); }
        else{
            throw new Exception("fileUploadSystem");
        }
    }
} else{
    throw new Exception("fileUploadUpload"); // ... OR THIS ERROR
}

// If anything was OK, we continue here with the uploaded file copied in our working dir to do some stuff with it...
?>

所以就我而言,我有fileUploadUpload或有fileUploadPartial例外。


调查

服务器端(php.ini 配置)

我检查了处理文件上传(使用ini_get命令)的 PHP 环境变量,以检查我没有超过最大文件大小或最大上传数。

一切似乎都很好,我有很大的限制,post_max_sizeupload_max_filesize. upload_tmp_dir是空的,我猜这意味着我使用默认的系统/tmp目录?

如果您发现问题或需要检查的其他事项,请告诉我。

注意:我无权访问php.ini,但这些值由我的托管服务提供商固定(我在共享托管上)。

file_uploads : '1'
upload_tmp_dir : ''
upload_max_filesize : '128M'
max_file_uploads : '20'
post_max_size : '130M'
max_execution_time : '300'

客户端(HTML/JS 代码)

MAX_FILE_SIZE小于我的 PHP 服务器允许的最大文件大小。

我使用enctype="multipart/form-data"method="post"符合预期。

我不做 AJAX 文件上传,只是在使用 JS 提交表单之前使用 Javascript 检查输入文件是否为空。

服务器端(PHP 代码)

当我调试内容时,$_FILES['iosImageFILE']我得到了这个fileUploadPartial错误(并且这个错误是空的fileUploadUpload)。

iosImageFILE = {"name":"DD292A1C-9CBF-4843-9E1C-7C815593C67A.png","type":"","tmp_name":"","error":3,"size":0}

服务器端(文件系统)

我试图检查/tmp上传文件的目录,但我无权访问它。我想检查它是否“充满旧的 tmp 文件”,但我想不是。

事实上,我制作了一个 PHP 脚本来扫描其内容var_export(scandir('/tmp')),但我只看到了一些sess_xxxxx会话文件(大约 7000 个文件)。

代码升级

我已将我的网站升级并增强为 https (以前是非安全 http),并将 PHP 版本从 5.6 升级到 7.0)。文件上传问题没有任何改变。

防火墙?!?

我可能怀疑我的托管服务提供商存在防火墙问题(我读过它可能会阻止一些关于文件上传的事情......)。但是他们说我的主机上没有激活防火墙...


结论

我真的不知道接下来要检查什么来调查和发现这个问题。

请注意,几乎所有上传文件的人都来自 iOS / Safari 浏览器。我不知道其他操作系统或浏览器是否会出现同样的问题......

我是一名前端 Web 开发人员,我必须承认我对这种问题感到不舒服。

任何帮助表示赞赏!

标签: phpiosfile-uploadimage-uploading

解决方案


故事结束:怀疑,这是我的托管服务提供商的问题(他们花了 1 个月的时间来解决它......)

我没有设法获得更多细节,除了这是一个“Apache配置问题”,并且它与负载平衡有一个链接......


推荐阅读