2016-01-11 3 views
16

Iam laden ein Skript zu schreiben, die Dateien per Drag and Drop mit jQuery uploads, die die Datei auf Drop liest und fügt sie zu einer Reihe von Dateien wie folgt:

var files = []; 

$(document).ready(function() { 
    jQuery.fn.dropbox = function(config) { 
     var dragging = 0; 
     var dragEnter = function(e) { 
      e.stopPropagation(); 
      e.preventDefault(); 
      dragging++; 
      $(".external-drop-indicator").fadeIn(); 
      $(".toast.toast-success").fadeIn().css("display", "inline-block");; 
      return false; 
     }; 
     var dragOver = function(e) { 
      e.stopPropagation(); 
      e.preventDefault(); 
      return false; 
     }; 
     var dragLeave = function(e) { 
      e.stopPropagation(); 
      e.preventDefault(); 
      dragging--; 
      if(dragging === 0) { 
       $(".external-drop-indicator").fadeOut(); 
       $(".toast.toast-success").fadeOut(); 
      } 
      return false; 
     }; 
     var drop = function(e) { 
      var dt = e.dataTransfer; 
      var files_upload = dt.files; 

      e.stopPropagation(); 
      e.preventDefault(); 

      if(files_upload && files_upload.length > 0 && config.onDrop !== undefined) { 
       files.push(files_upload); 
       config.onDrop(files_upload); 
      } 

      $(".external-drop-indicator").fadeOut(); 
      $(".toast.toast-success").fadeOut(); 

     }; 
     var applyDropbox = function(dropbox) { 
      dropbox.addEventListener('dragenter', dragEnter, false); 
      dropbox.addEventListener('dragover', dragOver, false); 
      dropbox.addEventListener('dragleave', dragLeave, false); 
      dropbox.addEventListener('drop', drop, false); 
     }; 
     return this.each(function() { 
      applyDropbox(this); 
     }); 
    }; 
}); 

Zusammenfassend fügt es eine erweiterte jQuery-Funktion hinzu, um Drag & Drop auf ein bestimmtes Element der Website zu ermöglichen, auf das die Funktion angewendet wird.

Dann wende ich die erweiterte Funktionalität, um den Körper für die Datei Drag zu aktivieren und Drop-Funktionalität wie folgt:

$(document).ready(function() { 
    $('body').dropbox({ 
     onDrop: function(f) { 
      $(f).each(function(idx, data) { 
       var file_name = data.name; 
       var extension = file_name.split('.'); 
       file_name = extension[0]; 
       extension = extension[1]; 
       if(extension == 'pdf' || extension == 'xls') { 
        showAjaxModal(base_url + 'index.php?modal/popup/file_create/' + folder_id + '/' + extension + '/' + file_name); 
       } else { 
        $(".upload-area").append('<div class="alert alert-danger" style="display:inline-block;width:480px;"><strong>Error!</strong> File type is incorrect.</div>'); 
       } 
      }); 
     } 
    }); 
}); 

Zusammengefasst, was das bedeutet ist, fügt die Drag & Drop-Funktionalität auf den Körper und wenn Wenn eine Datei gelöscht wird, erkennt sie die Erweiterung der Datei, indem sie den Namen und die Erweiterung aufteilt, sodass ich überprüfen kann, ob die Erweiterung der Datei, die gelöscht wurde, korrekt ist. Dann zeigt es ein Modal an, um Informationen über die Datei, die hochgeladen wird, für die spätere Übermittlung zu füllen, wenn die Dateierweiterung korrekt ist.

Dann gehe ich die Dateiinformationen mit CodeIgniter der Funktion „Form_Open()“ zu füllen, wenn die modalen Pops wie so:

<?php echo form_open(base_url() . 'index.php?client/file/create/' . $param2, array('class' => 'form-horizontal form-groups-bordered validate ajax-upload', 'enctype' => 'multipart/form-data')); ?> 

    <div class="col-md-4 file-info"> 
     <div class="icon-<?=($param3 == 'pdf' ? 'pdf' : 'document')?>"></div> 
     <p> 
      <?php echo $param4;?> 
     </p> 
    </div> 

    <div class="col-md-8 new-file"> 

     <div class="form-group"> 
      <div class="col-sm-12"> 
       <div class="input-group"> 
        <input type="text" class="form-control" name="tags" data-validate="required" data-message-required="Field is required" placeholder="File tags" value="" autofocus> 
       </div> 
      </div> 
     </div> 

     <div class="form-group"> 
      <div class="col-sm-12"> 
       <div class="input-group"> 
        <input type="text" class="form-control" name="name" data-validate="required" data-message-required="Field is required" placeholder="File name" value="" autofocus> 
       </div> 
      </div> 
     </div> 

     <div class="form-group"> 
      <div class="col-sm-12"> 
       <div class="input-group"> 
        <textarea rows="5" class="form-control" name="description" data-validate="required" data-message-required="Field is required" placeholder="File description" value="" autofocus></textarea> 
       </div> 
      </div> 
     </div> 

    </div> 

    <div class="form-group"> 
     <div class="col-sm-offset-4 col-sm-7"> 
      <button type="submit" class="btn btn-info" id="submit-button">Upload</button> 
      <span id="preloader-form"></span> 
     </div> 
    </div> 

<?php echo form_close(); ?> 

Dies schafft im Grunde eine Form, die über Ajax wird nachgereicht.

Nun gehe ich die Datei Vorlage über jQuery für die Informationen verarbeiten mit der Datei oder Dateien gesendet werden sollen, die wie so hochgeladen werden:

$(document).ready(function(e) { 
    $('.ajax-upload').submit(function(e) { 
     e.preventDefault(); 

     var $elm = $(this); 

     var fd = new FormData(); 

     for(var i = 0; i < files.length; i++) { 
      fd.append("file_" + i, files[i]); 
     } 

     var form_data = $(".ajax-upload").serializeArray(); 

     $.each(form_data, function(key, input) { 
      fd.append(input.name, input.value); 
     }); 

     var opts = { 
      url: $elm.attr('action'), 
      data: fd, 
      cache: false, 
      contentType: false, 
      processData: false, 
      type: 'POST', 
      beforeSend: uValidate, 
      success: showResponse 
     }; 

     if(fd.fake) { 
      opts.xhr = function() { 
       var xhr = jQuery.ajaxSettings.xhr(); 
       xhr.send = xhr.sendAsBinary; 
       return xhr; 
      } 
      opts.contentType = "multipart/form-data; boundary=" + fd.boundary; 
      opts.data = fd.toString(); 
     } 

     jQuery.ajax(opts); 

     return false; 
    }); 
}); 

Grundsätzlich ist die Form Standardaktion überschrieben und die Dateien, die wurden auf dem vorherigen Code-Chunk für die Drag-and-Drop-Funktionalität eingereicht werden nun an FormData, die später durch die Formulardaten, die auf dem Formular, das ich eingereicht wurde, verbunden ist, hinzugefügt. Dann wird die formData über einen AJAX-Aufruf gesendet.

Jetzt sieht der Controller wie diese, es behandelt den Anruf AJAX und führt dann die Datei-Upload-Methode auf dem Modell wie folgt:

function file($param1 = '', $param2 = '', $param3 = 0) { 
    if ($this->session->userdata('client_login') != 1) { 
     $this->session->set_userdata('last_page', current_url()); 
     redirect(base_url(), 'refresh'); 
    } 

    if ($param1 == 'create') 
     $this->crud_model->create_file($param2); 

    if ($param1 == 'edit') 
     $this->crud_model->update_file($param2); 

    if ($param1 == 'delete') 
     $this->crud_model->delete_file($param2, $param3); 

    $page_data['page_name'] = 'files'; 
    $page_data['page_title'] = 'Files List'; 
    $page_data['folder_id'] = $param3; 
    $this->load->view('backend/index', $page_data); 
} 

Hier ist das Modell Methode:

function create_file($folder_id) { 
    $data['name']   = $this->input->post('name'); 
    $data['tags']   = $this->input->post('tags'); 
    $data['description'] = $this->input->post('description'); 
    $data['type']   = 'file'; 
    $data['folder_id'] = $folder_id; 
    $data['client_id'] = $this->session->userdata('login_user_id'); 

    $config['upload_path'] = 'uploads/tmp/'; 
    $config['allowed_types'] = '*'; 
    $config['max_size'] = '100'; 

    $this->load->library('upload'); 
    $this->upload->initialize($config); 

    var_dump($_FILES); 
    die(); 

    foreach($_FILES as $field => $file) 
    { 
     //var_dump($_FILES); die();     
     // No problems with the file 
     if($file['error'] == 0) 
     { 
      // So lets upload 
      if ($this->upload->do_upload($field)) 
      { 
       $data = $this->upload->data(); 
       echo $data['full_path']; 
      } 
      else 
      { 
       $errors = $this->upload->display_errors(); 
       var_dump($errors); 
      } 
     } 
    } 

    $this->db->insert('client_files' , $data); 
} 

So Im Grunde ist das Array $ _FILES leer und die Datei wird nicht hochgeladen.

Die "Request Payload", wie auf Chrome Developer Tools betrachtet sieht wie folgt aus:

------WebKitFormBoundaryvVAxgIQd6qU8BtkF 
Content-Disposition: form-data; name="file_0" 

[object FileList] 
------WebKitFormBoundaryvVAxgIQd6qU8BtkF 
Content-Disposition: form-data; name="tags" 

bsd 
------WebKitFormBoundaryvVAxgIQd6qU8BtkF 
Content-Disposition: form-data; name="name" 

asd 
------WebKitFormBoundaryvVAxgIQd6qU8BtkF 
Content-Disposition: form-data; name="description" 

asd 

Und die Antwort, die ich von der var_dump get() auf dem Modell ist die folgende:

array(0) { 
} 

Ich habe die Lösung zu dieser Frage versucht: Sending multipart/formdata with jQuery.ajax Aber bisher kein Glück.

Jede Idee, was mache ich falsch und wie behebt man dieses Problem? Vielen Dank.

+0

Sie senden 'base_url + 'index.php? Modal/popup/file_create /' + folder_id + '/' + Erweiterung + '/' + Dateiname' von AJAX, aber die Serverseite erwartet nur' function create_file ($ folder_id) {'. Sehen Sie sich Ihre Routen an und/oder ändern Sie die CI-Methode, um die korrekte Anzahl der Parameter zu akzeptieren. – Tpojka

+0

@Tpojka Diese URL ist nur für das Modal, die eigentliche 'create_file ($ folder_id) ...' wird aufgerufen, wenn das Formular gesendet wird. Es hat nichts mit dem eigentlichen Datei-Upload zu tun. – Joscplan

Antwort

7

Das hier Problem ist, dass ich die Anordnung von Dateien anstelle der einzelnen Dateien auf der AJAX-Aufruf bin das Senden, speziell in diesem Teil des Codes:

for(var i = 0; i < files.length; i++) { 
    fd.append("file_" + i, files[i]); 
} 

Die Lösung Datei für Datei anhängen war auf die Formulardaten an Stelle der Anordnung von Dateien, etwa wie folgt:

for(var i = 0; i < files[0].length; i++) { 
    fd.append("file_" + i, files[i]); 
} 

Dies wird jede einzelne Datei der Dateien Array statt der Anordnung von Dateien selbst anhängen und es löst das Problem.

Abschließend wurde ich das Array von Dateien anstelle der einzelnen Dateien zu senden, der Hinweis darauf war die [object FileList], dass der Antrag wurde zeigt anstelle der Informationsdateien, die jetzt eine Anfrage wie das macht:

Content-Disposition: form-data; name="file"; filename="exfile.pdf" 
Content-Type: application/pdf 
Verwandte Themen