You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

CodeIgniter3多输入多文件上传异常:仅单个文件存入数据库求助

多组文件上传问题排查与修复

问题描述

实现多组other_title与other_file上传功能时,Controller循环处理仅能存入单个文件,其余文件无法正常写入数据库。

用户提供代码

View代码

<!-- Modal -->
<div class="form-row">
    <div class="form-group col-md-12">
        <label for="otitle">Other</label>
        <div class="form-row add-container">
            <div class="col-6">
                <input type="text" class="form-control" id="" name="other_title[]" placeholder="Input title" multiple>
            </div>
            <div class="col-5">
                <input class="form-control" type="file" name="other_file[]" id="" multiple>
            </div>
            <div class="col-auto">
                <a class="btn add-comp" style="border: 0; padding: 10px;"><i class="fa fa-plus" style="color: #006CF8;"></i></a>
            </div>
        </div>
    </div>
</div>
<!-- End Modal -->

Controller代码

public function actionBible($type, $id = null)
{
    $id_kategori = $this->input->post('id_kategori');
    $id_kategori = $id_kategori == NULL ? $this->input->post('nama_kategori') : $id_kategori;

    $data = array(
        'nama_bible' => $this->input->post('nama_bible'),
        'description' => $this->input->post('description'),
        'datasheet_title' => $this->input->post('datasheet_title'),
        'manual_title' => $this->input->post('manual_title'),
        'id_kategori' => $id_kategori,
        'created_by' => $this->session->userdata('nama_user'),
    );

    $folderUpload = "./uploads/bible/";
    $files = $_FILES;

    // datasheet
    $namaFile = $files['file']['name'];
    $lokasiTmp = $files['file']['tmp_name'];
    // # kita tambahkan uniqid() agar nama gambar bersifat unik
    $namaBaru = uniqid() . '-' . $namaFile;
    $lokasiBaru = "{$folderUpload}/{$namaBaru}";
    move_uploaded_file($lokasiTmp, $lokasiBaru);
    // manual
    $namaFileManual = $files['manual_file']['name'];
    $lokasiTmpManual = $files['manual_file']['tmp_name'];
    // # kita tambahkan uniqid() agar nama gambar bersifat unik
    $namaBaruManual = uniqid() . '-' . $namaFileManual;
    $lokasiBaruManual = "{$folderUpload}/{$namaBaruManual}";
    move_uploaded_file($lokasiTmpManual, $lokasiBaruManual);

    // datasheet
    $ktp = array('file' => $namaBaru);
    if ($namaFile != NULL) {
        $data = array_merge($data, $ktp);
    }
    // manual
    $manual = array('manual' => $namaBaruManual);
    if ($namaFileManual != NULL) {
        $data = array_merge($data, $manual);
    }

    // var_dump($data);
    if ($type == 'add') {
        $store = $this->db->insert('tb_bible', $data);
        if ($store) {
            // attachments
            $getLastId = $this->db->order_by('id_bible', 'DESC')->limit(1)->get('tb_bible')->row_array();

            $files = $_FILES;
            $jumlahFile = count($files['other_file']['name']);
            $other_title = $this->input->post('other_title');
            for ($i = 0; $i < $jumlahFile; $i++) {
                $data = array(
                    'id_bible' => $getLastId['id_bible'],
                    'id_other' => $this->input->post('id_other'),
                    'other_title' => $other_title[$i],
                    'created_at' => date('Y-m-d H:i:s')
                );
                $folderUpload = "./uploads/upnormal/";
                $files = $_FILES;

                $namaFileOther = $files['other_file']['name'][$i];
                $lokasiTmpOther = $files['other_file']['tmp_name'][$i];
                // # kita tambahkan uniqid() agar nama gambar bersifat unik
                $namaBaruOther = uniqid() . '-' . $namaFileOther;
                $lokasiBaruOther = "{$folderUpload}/{$namaBaruOther}";
                move_uploaded_file($lokasiTmpOther, $lokasiBaruOther);

                $other = array('other' => $namaBaruOther); // mengambil nama baru dan di upload ke dalam databases
                if ($namaFileOther != NULL) {
                    $data = array_merge($data, $other);
                    $this->db->insert('tb_other_bible', $data);
                }
            }
        }
    } elseif ($type == 'edit') {
        $this->db->update('tb_bible', $data, ['id_bible' => $this->input->post('id_bible')]);
    } else {
        $data = array(
            'delete' => 1
        );
        $this->db->update('tb_bible', $data, ['id_bible' => decrypt_url($id)]);
    }
    $this->session->set_flashdata('messageAlert', $this->messageAlert('success', "Data $type"));
    redirect('bible/guide');
}

问题根源

  1. 表单缺失enctype="multipart/form-data":这是文件上传的必要属性,未添加时后端仅能接收第一个文件,其余文件无法被正确传递。
  2. 循环次数依赖文件数量:以other_file的数量作为循环依据,若存在填写标题但未选择文件的情况,对应记录会被跳过;同时若标题数量多于文件数量,部分标题无法被处理。
  3. 循环内重复赋值冗余代码:$files = $_FILES在循环内重复定义,无实际作用且易混淆逻辑。
  4. 缺乏上传错误处理:未校验move_uploaded_file的执行结果,若文件上传失败,会导致数据库存入无效路径或直接跳过记录。
  5. 手动操作$_FILES风险:未使用CodeIgniter内置的上传类,无法利用框架的安全校验与错误处理机制。

修复方案

1. 修改View表单

确保包含文件上传的表单添加enctype="multipart/form-data"属性:

<form method="post" action="<?= site_url('bible/actionBible/add') ?>" enctype="multipart/form-data">
    <!-- 原有表单内容 -->
</form>

2. 修改Controller代码

public function actionBible($type, $id = null)
{
    $id_kategori = $this->input->post('id_kategori');
    $id_kategori = $id_kategori == NULL ? $this->input->post('nama_kategori') : $id_kategori;

    $data = array(
        'nama_bible' => $this->input->post('nama_bible'),
        'description' => $this->input->post('description'),
        'datasheet_title' => $this->input->post('datasheet_title'),
        'manual_title' => $this->input->post('manual_title'),
        'id_kategori' => $id_kategori,
        'created_by' => $this->session->userdata('nama_user'),
    );

    $folderUpload = "./uploads/bible/";
    // 初始化上传类配置
    $this->load->library('upload');

    // 处理datasheet文件
    if (!empty($_FILES['file']['name'])) {
        $config['upload_path'] = $folderUpload;
        $config['allowed_types'] = '*'; // 根据需求限制文件类型,如'pdf|doc'
        $config['file_name'] = uniqid() . '-' . $_FILES['file']['name'];
        $this->upload->initialize($config);
        
        if ($this->upload->do_upload('file')) {
            $uploadData = $this->upload->data();
            $data['file'] = $uploadData['file_name'];
        }
    }

    // 处理manual文件
    if (!empty($_FILES['manual_file']['name'])) {
        $config['upload_path'] = $folderUpload;
        $config['allowed_types'] = '*';
        $config['file_name'] = uniqid() . '-' . $_FILES['manual_file']['name'];
        $this->upload->initialize($config);
        
        if ($this->upload->do_upload('manual_file')) {
            $uploadData = $this->upload->data();
            $data['manual'] = $uploadData['file_name'];
        }
    }

    if ($type == 'add') {
        $store = $this->db->insert('tb_bible', $data);
        if ($store) {
            $getLastId = $this->db->insert_id(); // 直接获取刚插入的ID,比查最新记录更可靠
            $otherTitles = $this->input->post('other_title');
            $otherFiles = $_FILES['other_file'];
            $folderOther = "./uploads/upnormal/";

            // 以标题数量作为循环依据,确保每组标题都被处理
            foreach ($otherTitles as $index => $title) {
                // 跳过空标题
                if (empty(trim($title))) continue;
                
                $insertData = array(
                    'id_bible' => $getLastId,
                    'id_other' => $this->input->post('id_other'),
                    'other_title' => $title,
                    'created_at' => date('Y-m-d H:i:s')
                );

                // 处理对应文件
                if (!empty($otherFiles['name'][$index])) {
                    $config['upload_path'] = $folderOther;
                    $config['allowed_types'] = '*';
                    $config['file_name'] = uniqid() . '-' . $otherFiles['name'][$index];
                    $this->upload->initialize($config);
                    
                    if ($this->upload->do_upload('other_file', $index)) { // 指定上传索引
                        $uploadData = $this->upload->data();
                        $insertData['other'] = $uploadData['file_name'];
                    }
                }

                // 无论是否有文件,只要有标题就插入数据库
                $this->db->insert('tb_other_bible', $insertData);
            }
        }
    } elseif ($type == 'edit') {
        $this->db->update('tb_bible', $data, ['id_bible' => $this->input->post('id_bible')]);
    } else {
        $data = array('delete' => 1);
        $this->db->update('tb_bible', $data, ['id_bible' => decrypt_url($id)]);
    }

    $this->session->set_flashdata('messageAlert', $this->messageAlert('success', "Data $type"));
    redirect('bible/guide');
}

关键修复点说明

  • 使用$this->db->insert_id()获取刚插入的ID,比查询最新记录更高效可靠。
  • 以other_title的数量作为循环依据,确保每组标题都被处理,避免遗漏。
  • 引入CodeIgniter上传类,实现安全的文件上传与错误处理。
  • 移除冗余的重复赋值代码,简化逻辑。
  • 允许无文件但有标题的记录存入数据库(可根据需求调整)。

内容的提问来源于stack exchange,提问作者ucanggg2021

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 16:35:54