【问题标题】:Multiple file upload -- works fine when all documents are uploaded fails when only few are entered多文件上传——当所有文件上传失败时工作正常,只输入少数文件
【发布时间】:2014-10-14 08:56:21
【问题描述】:

我有这个表格,需要上传多个文件(最多 10 个文件)。这是html的样子:

<form action="fileupload.php" method="post" enctype="multipart/form-data">
<tr><td><input type="hidden" name="consultant_id" value="<?php echo $consult_id; ?>"></td></tr>

<tr><td>Offer letter:</td><td> Doc: <input type="file" name="myfile[]"></td></tr>
<tr><td>Project acceptance agreement:</td><td> Doc: <input type="file" name="myfile[]"></td></tr>
<tr><td>Employee book:</td><td> Doc: <input type="file" name="myfile[]"></td></tr>
<tr><td>W4 :</td><td> Doc: <input type="file" name="myfile[]"></td></tr>
<tr><td>State W4 :</td><td> Doc: <input type="file" name="myfile[]"></td></tr>
<tr><td><input type="submit" name="submit" value="Upload">  </td></tr>
</form></table>

我想将文件上传到服务器并将它们各自的路径存储在数据库(MySql)中。现在,当我向所有文件字段(上传所有 10 个文件)提供输入时,以下 php 代码工作得非常棒,但当我只想上传一些文件(比如 5 个)时失败。这是代码:

        <?php
    $consultant_id = $_POST['consultant_id'];
    echo $consultant_id;
    $verified_start_date = $_POST['verified_start_date'];

    // Assign valid types
    $valid_mime = array(
        'application/pdf',
        'image/jpeg',
        'image/jpg',



     );

    function upload($files, $dir, $size_limit=1024, $prevent_duplicate=false){
        global $valid_mime;

    // $files must be given.
    if(!isset($files)) return false;

    // Look for $valid_mime array.
    isset($valid_mime) and is_array($valid_mime) or die('Error in data resources, valid_mime array not found.');

    // Make directory if it does not exists. set permission to 0777.
    is_dir($dir) and chmod($dir, 0777) or mkdir($dir, 0777, true);
    //is_dir($consultant_id) and ($dir, 0777) or mkdir($dir/$consultant_id, 0777, true);
    $count = 1;
    foreach($files as $file){
        $file['error'] === UPLOAD_ERR_OK or die('Error in uploading file(s).');

        // Check uploaded-file type.
        in_array($file['type'], $valid_mime) or die();

        // Set size_limit in KB.
        $file['size'] > $size_limit*1024 and die('The uploaded file exceeds the maximum file size.');


        $file_extension = strrchr($file['name'], '.');
        $filename = basename($file['name'], $file_extension);

        $file_path = "{$dir}/{$filename}{$file_extension}";

        // Move uploaded-file from php temp folder to desire one.
        move_uploaded_file($file["tmp_name"], $file_path);

        // Make an array of filepaths
        $output[] = $file_path;
    }

    // Change permission of folder according to security issues.
    chmod($dir, 0755);

    return $output; 
}
/////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////  Controller Section  ////////////////////////////////

// Assign tmp_arr from $_FILES['myfile'] and do die if there is any problem.
$tmp_arr = (isset($_POST['submit']) and isset($_FILES['myfile'])) ? $_FILES['myfile'] : die('Error in posting data.');


// Create an array with desired structure.
for($i=0; $i<count($tmp_arr['name']); $i++){
    $files[] = array(
        'name'      =>  $tmp_arr['name'][$i],
        'type'      =>  $tmp_arr['type'][$i],
        'tmp_name'  =>  $tmp_arr['tmp_name'][$i],
        'error' =>  $tmp_arr['error'][$i],
        'size'      =>  $tmp_arr['size'][$i],
    );
}

// size_limit in KB
$path_arr = upload($files, './public/'.$consultant_id, 1024, true);
?>

我没有提到在数据库中输入数据的部分,因为我知道问题出在 $tmp_arr['error'][$i] 或 $file['error'] === UPLOAD_ERR_OK 或 die( '上传文件出错');

请看一下。

【问题讨论】:

  • 您的表单缺少multiple 一词,可能是问题所在。
  • @Fred-ii- 对不起,我没有找到你,缺少 multiple 在哪里?
  • 您可能应该对 $_FILES 数组执行 print_r。你的处理方式
  • 在这个页面上davidwalsh.name/multiple-file-upload 它显示&lt;input name="filesToUpload[]" id="filesToUpload" type="file" multiple="" /&gt; 然而,它可能是也可能不是问题,只是想我会提到它。
  • @Fred-ii- it multiple="" 表示用户可以为给定的输入标签选择多个文件。

标签: php html mysql file-upload multiple-file-upload


【解决方案1】:

问题似乎是当你有一个空白文件输入时,它返回一个'error' 值4,这意味着UPLOAD_ERR_NO_FILE。因此,由于该字段与UPLOAD_ERR_OK 不匹配,您可以通过调用die 立即停止所有代码,从而停止复制第一个空白之后的任何文件。如果第一个字段为空白,则不会到达 move_uploaded_file。如果十个中的第三个是空白的,那么前两个文件将被复制,当第三个被处理时,它将停止任何进一步的文件。但是您仍然会看到错误“上传文件时出错”。

编辑:

<?php
$consultant_id = $_POST['consultant_id'];
echo $consultant_id;
$verified_start_date = $_POST['verified_start_date'];

// Assign valid types
$valid_mime = array(
    'application/pdf',
    'image/jpeg',
    'image/jpg',



 );

function upload($files, $dir, $size_limit=1024, $prevent_duplicate=false){
    global $valid_mime;

    // $files must be given.
    if(!isset($files)) return false;

    //please use proper if statements. This is confusing.
    //isset($valid_mime) and is_array($valid_mime) or die('Error in data resources, valid_mime array not found.');

    // Look for $valid_mime array.
    if(!isset($valid_mime) || !is_array($valid_mime)) {
        die('Error in data resources, valid_mime array not found.');
    }

    //please use proper if statements. This is confusing.
    // is_dir($dir) and chmod($dir, 0777) or mkdir($dir, 0777, true);

    // Make directory if it does not exists. set permission to 0777.
    if(!is_dir($dir)) {
        mkdir($dir, 0777, true);
    } else {
        //try to chmod if the directory does exist
        chmod($dir, 0777);
    }

    if(!is_writable($dir)){
        die('Error unable to write to specified directory.');
    }

    foreach($files as $key=>$file){
        //switch case on the error code
        //you can find a list of these error codes at: http://php.net/manual/en/features.file-upload.errors.php
        switch($file['error']){
            default:
                //triggered if an unknown error happened. Newer php versions might bring new constants.
                //log error for this file
                $output[$key] = array('error'=>true, 'message'=>'An unknown error occurred');
                break;
            case UPLOAD_ERR_INI_SIZE:
                //log error for this file
                $output[$key] = array('error'=>true, 'message'=>'File size exceeds ini setting');
                break;
            case UPLOAD_ERR_FORM_SIZE:
                //log error for this file
                $output[$key] = array('error'=>true, 'message'=>'File size exceeds MAX_FILE_SIZE setting');
                break;
            case UPLOAD_ERR_PARTIAL:
                //log error for this file
                $output[$key] = array('error'=>true, 'message'=>'File was only partially uploaded');
                break;
            case UPLOAD_ERR_NO_FILE:
                //log error for this file
                $output[$key] = array('error'=>true, 'message'=>'File input was blank');
                break;
            case UPLOAD_ERR_NO_TMP_DIR:
                //log error for this file
                $output[$key] = array('error'=>true, 'message'=>'Missing temporary folder');
                break;
            case UPLOAD_ERR_CANT_WRITE:
                //log error for this file
                $output[$key] = array('error'=>true, 'message'=>'Failed to write file to disk');
                break;
            case UPLOAD_ERR_OK:
                //upload worked fine
                // Check uploaded-file type.
                if(in_array($file['type'], $valid_mime)){
                    // Set size_limit in KB.
                    if($file['size'] <= $size_limit*1024){
                        //get the file extension.
                        $file_extension = strrchr($file['name'], '.');
                        //get the filename
                        $filename = basename($file['name'], $file_extension);
                        //full filename and path
                        $file_path = "{$dir}/{$filename}{$file_extension}";

                        // Move uploaded-file from php temp folder to desire one.
                        // function returns true if the move was successful
                        if(move_uploaded_file($file["tmp_name"], $file_path)){
                            $output[$key] = array('error'=>false, 'message'=>'File was uploaded successfully', 'file'=>$file_path);
                        } else {
                            $output[$key] = array('error'=>true, 'message'=>'Unspecified error when moving the uploaded file');
                        }
                    } else {
                        //log error for this file
                        $output[$key] = array('error'=>true, 'message'=>'The uploaded file exceeds the maximum file size');
                    }
                } else {
                    //log error for this file
                    $output[$key] = array('error'=>true, 'message'=>'Failed to write file to disk');
                }
        }
    }

    // Change permission of folder according to security issues.
    chmod($dir, 0755);

    return $output; 
}

/////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////  Controller Section  ////////////////////////////////

// Assign tmp_arr from $_FILES['myfile'] and do die if there is any problem.
$tmp_arr = (isset($_POST['submit']) and isset($_FILES['myfile'])) ? $_FILES['myfile'] : die('Error in posting data.');


// Create an array with desired structure.
for($i=0; $i<count($tmp_arr['name']); $i++){
    $files[] = array(
        'name'      =>  $tmp_arr['name'][$i],
        'type'      =>  $tmp_arr['type'][$i],
        'tmp_name'  =>  $tmp_arr['tmp_name'][$i],
        'error' =>  $tmp_arr['error'][$i],
        'size'      =>  $tmp_arr['size'][$i],
    );
}

// size_limit in KB
$path_arr = upload($files, './public/'.$consultant_id, 1024, true);

如果我这样做,这就是我会使用的功能。如果一个上传的文件有问题,它不会阻止其余文件的上传,并将 $_FILES 中的'error' 键转换为更用户友好的消息。您可以轻松地遍历返回数组并检查布尔“错误”键以查看特定文件是否有问题。如果“错误”为真,您可以回显该消息以供用户查看。如果没有错误,则会显示“文件已成功上传”消息。返回数组中的键对应于传入数组中的相同键。因此,$file[0] 与 $returnResult[0] 是同一个文件,以便于参考。

【讨论】:

  • 没错!所以我该怎么做?如果我删除die,问题会解决吗?
  • 您可能应该在进行其余检查之前检查'error' 是否等于UPLOAD_ERROR_NO_FILE,如果它为空白则跳过它。此外,在这些情况下使用die 可能会导致更多问题,因为您并没有真正了解剩余的问题是什么。我会试着为你清理一下,然后展示它可能会变得更好。
  • 谢谢 :) 但它仍然无法正常工作。你能告诉我应该做哪些改变吗?我不确定这个error 报告是如何工作的。我尝试使用“error 等于UPLOAD_ERR_NO_FILE”,这不会影响我要上传的文件(UPLOAD_ERR_OK 文件)
  • 非常感谢!这段代码很棒。但是,我想输出有文件的路径或没有上传文件的 NULL。现在它输出 Array。让我自己试试。 :) 再次感谢您解决问题! :)
  • 遍历返回的数组并输出'error'键为假的'message'键。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-06-30
  • 2013-06-09
  • 2012-03-18
  • 2012-04-28
相关资源
最近更新 更多