dropzone块上传:我应该使用什么回调来调用ajax并处理文件/块?

时间:2018-10-16 15:00:50

标签: javascript php ajax dropzone.js

我正在尝试使用dropzone js和php正确实现块上传。我主要关心的是:我应该在哪里进行ajax调用?通常(没有任何块),您只需指定URL参数。但是,对于块来说,这还不够,我想,因为将只有1个ajax调用,但是理想情况下,块将是几个,我们必须等待全部,然后再用php重新组装整个文件。因此,以您的经验,执行ajax调用或在哪里调用的正确位置是什么? (也许这是只打一个电话的方法吗?)。这是我当前代码的简单摘录:

window['dropzone' + panel_index] = new Dropzone(
  selector,
  {
    url: ajax_url + '?action=uploadfile'
    ,addRemoveLinks: true
    ,maxFiles: 5
    ,maxFilesize: maxfilesize
    ,uploadMultiple:false
    ,parallelUploads: 1
    ,chunking:true
    ,forceChunking:true
    ,chunkSize:10485760 // 10Mb
    ,retryChunks: true   // retry chunks on failure
    ,retryChunksLimit: 3
    ,chunksUploaded:function(file, done){
      // called only once, when chunks are finished > do something ajax > php to reassemble the file?
      done();
    }
    ,params: function(file, xhr, chunk){

      // called once per every chunk > do something ajax > php?

      if(chunk){
        $.extend(true, p, {
          dzuuid: chunk.file.upload.uuid,
          dzchunkindex: chunk.index,
          dztotalfilesize: chunk.file.size,
          dzchunksize: this.options.chunkSize,
          dztotalchunkcount: chunk.file.upload.totalChunkCount,
          dzchunkbyteoffset: chunk.index * this.options.chunkSize
        });
      }

      return p;
    }// params


    ,init: function(){
      this.on('success', function(newfile){
        // called after chunksUploaded > do something ajax > php?
      });// onsuccess

      this.on('uploadprogress', function(file, progress, bytesent){
        // called continuously
      })
    }// dropzone init option
  }// dropzone options
);

2 个答案:

答案 0 :(得分:0)

简而言之,服务方块处理所需的唯一回调是传递给params的函数。这样的东西(摘录自我的代码):

,params: function(files, xhr, chunk){

  var p = { // $_POST
    app_type: 'configurator'
    ,app_code: manager.code
    ,file_types: filetypes
    ,max_filesize: maxfilesize
    ,upf: upf
  }

  if(chunk){
    $.extend(true, p, {
      dzuuid: chunk.file.upload.uuid,
      dzchunkindex: chunk.index,
      dztotalfilesize: chunk.file.size,
      dzchunksize: this.options.chunkSize,
      dztotalchunkcount: chunk.file.upload.totalChunkCount,
      dzchunkbyteoffset: chunk.index * this.options.chunkSize
    });
  }

  return p;
}// params

被调用的url只是一般dropzone的url参数。每块调用一次。

例如,在php中,您可以使用$ _POST ['dzchunkindex']保存名称已修改的块。

// do all the sanitisation tasks, then:
$target_chunk = $this->target_path . DS . $filename . $chunk_index;
// and then do the file saving tasks

在处理完所有块之后,您将拥有与服务器上的块一样多的文件。然后,在同一函数上,检查块索引是否像dztotalchunkcount - 1一样(在其他情况下,如果当前块是最后一个),并且在这种情况下,还将所有块合并到一个文件中。示例:

if($chunk_index == $total_chunks - 1){
  $final = fopen($target_file, 'wb');   // Open for write and start from beginning of file
  for ($i = 0; $i < $total_chunks; $i++) {
    $file = fopen($target_file.$i, 'rb');
    while($buff = fread($file, 4096)){ fwrite($final, $buff); }
    fclose($file);
    unlink($target_file.$i);
  }
  fclose($final);
}

答案 1 :(得分:0)

我正在chunksUploaded选项中执行此操作。在Dropzone为我上传了所有块之后,我在chunksUploaded内执行了另一个ajax调用,该调用与我的上传器连接到一个单独的PHP脚本,该脚本连接了所有上传的文件。

因此,每个块上传均调用与PHP中的块上传相同的Dropzone网址:

<?php

/* ========================================
  VARIABLES
======================================== */

// chunk variables
$fileId = $_POST['dzuuid'];
$chunkIndex = $_POST['dzchunkindex'] + 1;
$chunkTotal = $_POST['dztotalchunkcount'];

// file path variables
$ds = DIRECTORY_SEPARATOR;
$targetPath = dirname( __FILE__ ) . "{$ds}uploads{$ds}";
$fileType = strtolower(pathinfo($_FILES['file']['name'], PATHINFO_EXTENSION));
$fileSize = $_FILES["file"]["size"];
$filename = "{$fileId}-{$chunkIndex}.{$fileType}";
$targetFile = $targetPath . $filename;

/* ========================================
  DEPENDENCY FUNCTIONS
======================================== */

$returnResponse = function ($info = null, $filelink = null, $status = "error") {
  die (json_encode( array(
    "status" => $status,
    "info" => $info,
    "file_link" => $filelink
  )));
};

/* ========================================
  VALIDATION CHECKS
======================================== */

// I deleted a bunch of validation that goes here to keep the code short

/* ========================================
  CHUNK UPLOAD
======================================== */

move_uploaded_file($_FILES['file']['tmp_name'], $targetFile);

// Be sure that the file has been uploaded
if ( !file_exists($targetFile) ) $returnResponse("An error occurred and we couldn't upload the requested file.");
chmod($targetFile, 0777) or $returnResponse("Could not reset permissions on uploaded chunk.");

$returnResponse(null, null, "success");

然后,chunksUploaded对串联php脚本执行另一个ajax调用(注意,我如何使用放置区上传ID作为序列来识别哪些文件块属于一起):

<?php

// get variables
$fileId = $_GET['dzuuid'];
$chunkTotal = $_GET['dztotalchunkcount'];

// file path variables
$ds = DIRECTORY_SEPARATOR;
$targetPath = dirname( __FILE__ ) . "{$ds}uploads{$ds}";
//$fileType = strtolower(pathinfo($_GET['fileName'], PATHINFO_EXTENSION));
$fileType = $_GET['fileName'];

/* ========================================
  DEPENDENCY FUNCTIONS
======================================== */

$returnResponse = function ($info = null, $filelink = null, $status = "error") {
  die (json_encode( array(
    "status" => $status,
    "info" => $info,
    "file_link" => $filelink
  )));
};

/* ========================================
  CONCATENATE UPLOADED FILES
======================================== */

// loop through temp files and grab the content
for ($i = 1; $i <= $chunkTotal; $i++) {

  // target temp file
  $temp_file_path = realpath("{$targetPath}{$fileId}-{$i}.{$fileType}") or $returnResponse("Your chunk was lost mid-upload.");

  // copy chunk
  $chunk = file_get_contents($temp_file_path);
  if ( empty($chunk) ) $returnResponse("Chunks are uploading as empty strings.");

  // add chunk to main file
  file_put_contents("{$targetPath}{$fileId}.{$fileType}", $chunk, FILE_APPEND | LOCK_EX);

  // delete chunk
  unlink($temp_file_path);
  if ( file_exists($temp_file_path) ) $returnResponse("Your temp files could not be deleted.");

}

// and by the time you get here you should have your concatenated file in the "uploads" folder to do with what you want