Laravel 10中Dropzone文件上传无法写入数据库问题求助
Dropzone多文件上传后Files字段无法写入数据库问题修复
问题背景
使用Dropzone实现表单多文件上传,对应数据库表字段Files,提交表单后该字段为空,文件也未存入指定存储目录。注释掉$request->validate(Aplicacione::$rules);后,文件能成功上传到目录,但Files字段仍无法写入数据库,其他表单功能正常。
相关代码
控制器store方法
public function store(Request $request) { // Eliminar el campo 'Files' del array $request antes de la validación $files = $request->input('Files'); unset($request['Files']); // Validación para otros campos del formulario $request->validate(Aplicacione::$rules); // Restaurar el campo 'Files' después de la validación si existe $request['Files'] = $files; // Lógica para manejar la carga de los documentos $uploadedFiles = []; if ($request->hasFile('Files')) { foreach ($request->file('Files') as $file) { // Puedes agregar lógica específica para manejar documentos si es necesario // Ejemplo: Guardar el documento en una ubicación específica $fileName = $file->getClientOriginalName(); $file->move(public_path('storage/files/'), $fileName); // Agregar el nombre del archivo a la lista de archivos cargados $uploadedFiles[] = $fileName; } } // Agregar los nombres de los archivos a la solicitud para almacenarlos en la base de datos $request['Files'] = $uploadedFiles; dd($request->all()); // Lógica para manejar la carga de las firmas como imágenes $folderPath = public_path('storage/upload/'); // Manejar la firma del propietario $ownerSignature = $request->input('OwnerSignature'); $this->handleSignature($ownerSignature, $folderPath, 'owner_signature'); // Manejar la firma del segundo propietario $owner2Signature = $request->input('Owner2Signature'); $this->handleSignature($owner2Signature, $folderPath, 'owner2_signature'); // Crear una nueva instancia de Aplicacione con los datos del formulario $aplicacione = Aplicacione::create($request->all()); return redirect()->route('aplicaciones.index') ->with('success', 'Aplicacione created successfully.'); }
模型Aplicacione代码
class Aplicacione extends Model { static $rules = [ 'LegalBusinessName' => 'required', 'bda' => 'required', 'TaxID' => 'required', 'BusinessClass' => 'required', 'Street' => 'required', 'City' => 'required', 'State' => 'required', 'ZipCode' => 'required', 'BusinessPhone' => 'required', 'ProductsSold' => 'required', 'Email' => 'required', 'OwnerName' => 'required', 'Ownertreet' => 'required', 'OwnerCity' => 'required', 'OwnerState' => 'required', 'OwnerZipCode' => 'required', 'OwnerHomePhone' => 'required', 'OwnerCellPhone' => 'required', 'OwnerLicense' => 'required', 'OwnerSocial' => 'required', 'CurrentCash' => 'required', 'OwnerSignature' => 'required', 'Files' => 'sometimes|array', // Modifica la regla para permitir arrays o nulo ]; protected $perPage = 20; /** * Attributes that should be mass-assignable. * * @var array */ protected $fillable = ['AgentesId','LegalBusinessName','bda','LegalEntity','Other','TaxID','BusinessClass','Street','City','State','ZipCode','BusinessPhone','MonthlyDeposit','ProductsSold','Email','Years','Months','OwnerName','Ownertreet','OwnerCity','OwnerState','OwnerZipCode','OwnerHomePhone','OwnerCellPhone','OwnerTitle','OwnerOwnership','OwnerLicense','OwnerState2','OwnerDateBirth','OwnerSocial','isCoApplicant','Owner2Name','Owner2treet','Owner2City','Owner2State','Owner2ZipCode','Owner2HomePhone','Owner2CellPhone','Owner2Title','Owner2Ownership','Owner2License','Owner2State2','Owner2DateBirth','Owner2Social','DesiredAmount','UseFunds','CurrentCash','CompanyName','Balance','AppDate','CoApplicant','Files','OwnerSignature','Owner2Signature','Estado','ApproveAmout']; /** * The attributes that should be cast to native types. * * @var array */ protected $casts = [ 'Files' => 'array', ]; }
前端Dropzone HTML
<!--begin::Dropzone--> <div class="dropzone" id="upload_files"> <!-- Message para Dropzone --> <div class="dz-message needsclick"> <i class="fa-solid fa-cloud-arrow-up fs-5x text-primary"></i> <!-- Info sobre la carga de archivos --> <div class="ms-4"> <h3 class="fs-3 fw-bold text-gray-900 mb-1">Drop files here or click to upload.</h3> <span class="fs-4 text-danger mb-1">Uploading the requested files is required.</span><br> <span class="fs-4 text-danger">Copy of Driver’s License</span><br> <span class="fs-4 text-danger">Copy of Business License</span><br> <span class="fs-4 text-danger">Copy of Voided Check</span><br> <span class="fs-4 text-danger">4 Last Bank Statement</span><br> <span class="fs-4 fw-semibold text-gray-500">Upload up to 20 files</span> </div> </div> <!-- Fin de Message --> </div> <!-- Fin de Dropzone -->
Dropzone JS配置
<script> Dropzone.autoDiscover = false; var myDropzone = new Dropzone("#upload_files", { url: "{{ route('aplicaciones.store') }}", paramName: "Files", // Ajusta el nombre del parámetro según tu controlador maxFiles: 20, maxFilesize: 20, // MB addRemoveLinks: true, uploadMultiple: true, // Permitir la carga de múltiples archivos acceptedFiles: "image/*,application/pdf,application/msword", headers: { 'X-CSRF-TOKEN': "{{ csrf_token() }}" }, success: function (file, response) { // Lógica después de que se carga el archivo, si es necesario $('form').append('<input type="hidden" name="Files[]" value="' + response.name + '">'); console.log(response); }, error: function (file, response) { // Lógica en caso de error, si es necesario console.log(response); }, init: function () { @if(isset($project) && $project->document) var files = {!! json_encode($project->document) !!}; for (var i in files) { var file = files[i]; this.options.addedfile.call(this, file); file.previewElement.classList.add('dz-complete'); $('form').append('<input type="hidden" name="Files[]" value="' + file.file_name + '">'); } @endif } }); </script>
修复步骤
1. 修复控制器中文件对象丢失问题
当前代码用$request->input('Files')保存的是普通输入值,不是上传的文件对象,验证后无法恢复文件。修改如下:
// 保存文件对象而非input值 $files = $request->file('Files'); unset($request['Files']); $request->validate(Aplicacione::$rules); // 恢复文件对象到请求中 if ($files) { $request->files->set('Files', $files); }
2. 调整Dropzone上传逻辑,和表单同步提交
当前Dropzone会单独上传文件,导致表单提交时的文件数据不匹配。修改JS配置,让文件和表单一起提交:
<script> Dropzone.autoDiscover = false; var myDropzone = new Dropzone("#upload_files", { url: "{{ route('aplicaciones.store') }}", paramName: "Files", maxFiles: 20, maxFilesize: 20, addRemoveLinks: true, uploadMultiple: true, acceptedFiles: "image/*,application/pdf,application/msword", headers: { 'X-CSRF-TOKEN': "{{ csrf_token() }}" }, autoProcessQueue: false, // 关闭自动上传,等待表单提交 init: function () { let dropzone = this; // 监听表单提交,先处理文件上传 $('form').submit(function(e) { if (dropzone.getQueuedFiles().length > 0) { e.preventDefault(); dropzone.processQueue(); return false; } }); // 所有文件上传完成后,提交表单 this.on("queuecomplete", function() { $('form')[0].submit(); }); // 原有初始化代码保留 @if(isset($project) && $project->document) var files = {!! json_encode($project->document) !!}; for (var i in files) { var file = files[i]; this.options.addedfile.call(this, file); file.previewElement.classList.add('dz-complete'); $('form').append('<input type="hidden" name="Files[]" value="' + file.file_name + '">'); } @endif } }); </script>
3. 优化控制器文件处理与数据库写入
- 去掉
dd($request->all());,否则代码不会执行到创建模型的步骤 - 建议重命名文件避免同名覆盖
- 用
merge方法更安全地添加数据到请求:
// 处理文件 $uploadedFiles = []; if ($request->hasFile('Files')) { foreach ($request->file('Files') as $file) { // 加时间戳避免文件名重复 $fileName = time() . '_' . $file->getClientOriginalName(); $file->move(public_path('storage/files/'), $fileName); $uploadedFiles[] = $fileName; } } // 将文件名数组合并到请求中 $request->merge(['Files' => $uploadedFiles]); // 移除调试代码 // dd($request->all()); // 创建模型实例 $aplicacione = Aplicacione::create($request->all());
4. 完善文件验证规则
为Files数组添加单个文件的验证规则,确保上传文件符合要求:
static $rules = [ // 其他必填规则... 'Files' => 'required|array', // 根据需求改成required或sometimes 'Files.*' => 'file|mimes:jpeg,png,pdf,doc,docx|max:20480', // 限制文件类型和大小(20MB) ];
内容的提问来源于stack exchange,提问作者Ray Duran
相关产品推荐
相关产品推荐

