php - Uploading files in Fine-Uploader, fail to combine/merge chunks after successful upload -
so i've been trying chunked uploading working project i've been working on, i'm pretty new things, in fact intensive purposes can consider me complete noob teaching himself, i'm using manual upload template website, , traditional server side example files gain understanding of how code works , trying piece them functional example me build from. i've been able things working.
i've managed uploading regular files files folder if upload file without chunking goes files directory, if use chunking works chunk file , upload folder in chunks directory, cant seem figure out how put chunks , place in files directory
my firefox console gives me response , stops after finishing uploading file in chunks regardless of if have chunking success endpoint included in code or not makes me think it's got chunking success endpoint not being set correctly or along lines.
[fine uploader 5.11.8] chunks have been uploaded 0 - finalizing....fine-uploader.js:162:21 [fine uploader 5.11.8] received response status 200 body: {"success":true,"uuid":"79e7db33-9609-49cd-bcb1-2606bea6abd7","uploadname":null}fine-uploader.js:162:21 [fine uploader 5.11.8] finalize successful 0
i've spent 2 days researching no avail, don't seem getting errors, said i'm pretty noob when comes understanding on own. appreciated.
here uploader code body
<body> <!-- fine uploader dom element ====================================================================== --> <div id="fine-uploader-manual-trigger"></div> <!-- code create instance of fine uploader , bind dom/template ====================================================================== --> <script> var manualuploader = new qq.fineuploader({ debug: true, element: document.getelementbyid('fine-uploader-manual-trigger'), template: 'qq-template-manual-trigger', request: { endpoint: 'endpoint.php' }, chunking: { enabled: true }, success: { endpoint: "endpoint.php?done" }, resume: { enabled: true }, thumbnails: { placeholders: { waitingpath: 'images/waiting-generic.png', notavailablepath: 'images/not_available-generic.png' } }, autoupload: false, showmessage: function(message) { //show message if error occur during upload process alert(message); } }); qq(document.getelementbyid("trigger-upload")).attach("click", function() { manualuploader.uploadstoredfiles(); }); </script> </body> </html>
here endpoint.php file
require_once "handler.php"; $uploader = new uploadhandler(); // specify list of valid extensions, ex. array("jpeg", "xml", "bmp") $uploader->allowedextensions = array(); // files types allowed default // specify max file size in bytes. $uploader->sizelimit = null; // specify input name set in javascript. $uploader->inputname = "qqfile"; // matches fine uploader's default inputname value default // if want use chunking/resume feature, specify folder temporarily save parts. $uploader->chunksfolder = "chunks"; $method = $_server["request_method"]; if ($method == "post") { header("content-type: text/plain"); // assumes have chunking.success.endpoint set point here query parameter of "done". // example: /myserver/handlers/endpoint.php?done if (isset($_get["done"])) { $result = $uploader->combinechunks("files"); } // handles upload requests else { // call handleupload() name of folder, relative php's getcwd() $result = $uploader->handleupload("files"); // return name used uploaded file can use following line. $result["uploadname"] = $uploader->getuploadname(); } echo json_encode($result); } // delete file requests else if ($method == "delete") { $result = $uploader->handledelete("files"); echo json_encode($result); } else { header("http/1.0 405 method not allowed"); } ?>
here handler.php file, i'm using default traditional server side example.
class uploadhandler { public $allowedextensions = array(); public $sizelimit = null; public $inputname = 'qqfile'; public $chunksfolder = 'chunks'; public $chunkscleanupprobability = 0.001; // once in 1000 requests on avg public $chunksexpirein = 604800; // 1 week protected $uploadname; /** * original filename */ public function getname(){ if (isset($_request['qqfilename'])) return $_request['qqfilename']; if (isset($_files[$this->inputname])) return $_files[$this->inputname]['name']; } public function getinitialfiles() { $initialfiles = array(); ($i = 0; $i < 5000; $i++) { array_push($initialfiles, array("name" => "name" + $i, uuid => "uuid" + $i, thumbnailurl => "")); } return $initialfiles; } /** * name of uploaded file */ public function getuploadname(){ return $this->uploadname; } public function combinechunks($uploaddirectory, $name = null) { $uuid = $_post['qquuid']; if ($name === null){ $name = $this->getname(); } $targetfolder = $this->chunksfolder.directory_separator.$uuid; $totalparts = isset($_request['qqtotalparts']) ? (int)$_request['qqtotalparts'] : 1; $targetpath = join(directory_separator, array($uploaddirectory, $uuid, $name)); $this->uploadname = $name; if (!file_exists($targetpath)){ mkdir(dirname($targetpath), 0777, true); } $target = fopen($targetpath, 'wb'); ($i=0; $i<$totalparts; $i++){ $chunk = fopen($targetfolder.directory_separator.$i, "rb"); stream_copy_to_stream($chunk, $target); fclose($chunk); } // success fclose($target); ($i=0; $i<$totalparts; $i++){ unlink($targetfolder.directory_separator.$i); } rmdir($targetfolder); if (!is_null($this->sizelimit) && filesize($targetpath) > $this->sizelimit) { unlink($targetpath); http_response_code(413); return array("success" => false, "uuid" => $uuid, "preventretry" => true); } return array("success" => true, "uuid" => $uuid); } /** * process upload. * @param string $uploaddirectory target directory. * @param string $name overwrites name of file. */ public function handleupload($uploaddirectory, $name = null){ if (is_writable($this->chunksfolder) && 1 == mt_rand(1, 1/$this->chunkscleanupprobability)){ // run garbage collection $this->cleanupchunks(); } // check max upload size specified in class configuration not // exceed size allowed server config if ($this->tobytes(ini_get('post_max_size')) < $this->sizelimit || $this->tobytes(ini_get('upload_max_filesize')) < $this->sizelimit){ $neededrequestsize = max(1, $this->sizelimit / 1024 / 1024) . 'm'; return array('error'=>"server error. increase post_max_size , upload_max_filesize ".$neededrequestsize); } if ($this->isinaccessible($uploaddirectory)){ return array('error' => "server error. uploads directory isn't writable"); } $type = $_server['content_type']; if (isset($_server['http_content_type'])) { $type = $_server['http_content_type']; } if(!isset($type)) { return array('error' => "no files uploaded."); } else if (strpos(strtolower($type), 'multipart/') !== 0){ return array('error' => "server error. not multipart request. please set forcemultipart default value (true)."); } // size , name $file = $_files[$this->inputname]; $size = $file['size']; if (isset($_request['qqtotalfilesize'])) { $size = $_request['qqtotalfilesize']; } if ($name === null){ $name = $this->getname(); } // check file error if($file['error']) { return array('error' => 'upload error #'.$file['error']); } // validate name if ($name === null || $name === ''){ return array('error' => 'file name empty.'); } // validate file size if ($size == 0){ return array('error' => 'file empty.'); } if (!is_null($this->sizelimit) && $size > $this->sizelimit) { return array('error' => 'file large.', 'preventretry' => true); } // validate file extension $pathinfo = pathinfo($name); $ext = isset($pathinfo['extension']) ? $pathinfo['extension'] : ''; if($this->allowedextensions && !in_array(strtolower($ext), array_map("strtolower", $this->allowedextensions))){ $these = implode(', ', $this->allowedextensions); return array('error' => 'file has invalid extension, should 1 of '. $these . '.'); } // save chunk $totalparts = isset($_request['qqtotalparts']) ? (int)$_request['qqtotalparts'] : 1; $uuid = $_request['qquuid']; if ($totalparts > 1){ # chunked upload $chunksfolder = $this->chunksfolder; $partindex = (int)$_request['qqpartindex']; if (!is_writable($chunksfolder) && !is_executable($uploaddirectory)){ return array('error' => "server error. chunks directory isn't writable or executable."); } $targetfolder = $this->chunksfolder.directory_separator.$uuid; if (!file_exists($targetfolder)){ mkdir($targetfolder, 0777, true); } $target = $targetfolder.'/'.$partindex; $success = move_uploaded_file($_files[$this->inputname]['tmp_name'], $target); return array("success" => true, "uuid" => $uuid); } else { # non-chunked upload $target = join(directory_separator, array($uploaddirectory, $uuid, $name)); if ($target){ $this->uploadname = basename($target); if (!is_dir(dirname($target))){ mkdir(dirname($target), 0777, true); } if (move_uploaded_file($file['tmp_name'], $target)){ return array('success'=> true, "uuid" => $uuid); } } return array('error'=> 'could not save uploaded file.' . 'the upload cancelled, or server error encountered'); } } /** * process delete. * @param string $uploaddirectory target directory. * @params string $name overwrites name of file. * */ public function handledelete($uploaddirectory, $name=null) { if ($this->isinaccessible($uploaddirectory)) { return array('error' => "server error. uploads directory isn't writable" . ((!$this->iswindows()) ? " or executable." : ".")); } $targetfolder = $uploaddirectory; $url = parse_url($_server['request_uri'], php_url_path); $tokens = explode('/', $url); $uuid = $tokens[sizeof($tokens)-1]; $target = join(directory_separator, array($targetfolder, $uuid)); if (is_dir($target)){ $this->removedir($target); return array("success" => true, "uuid" => $uuid); } else { return array("success" => false, "error" => "file not found! unable delete.".$url, "path" => $uuid ); } } /** * returns path use upload. check name not exist, * , appends suffix otherwise. * @param string $uploaddirectory target directory * @param string $filename name of file use. */ protected function getuniquetargetpath($uploaddirectory, $filename) { // allow 1 process @ time unique file name, otherwise // if multiple people upload file same name @ same time // latest saved. if (function_exists('sem_acquire')){ $lock = sem_get(ftok(__file__, 'u')); sem_acquire($lock); } $pathinfo = pathinfo($filename); $base = $pathinfo['filename']; $ext = isset($pathinfo['extension']) ? $pathinfo['extension'] : ''; $ext = $ext == '' ? $ext : '.' . $ext; $unique = $base; $suffix = 0; // unique file name file, appending random suffix. while (file_exists($uploaddirectory . directory_separator . $unique . $ext)){ $suffix += rand(1, 999); $unique = $base.'-'.$suffix; } $result = $uploaddirectory . directory_separator . $unique . $ext; // create empty target file if (!touch($result)){ // failed $result = false; } if (function_exists('sem_acquire')){ sem_release($lock); } return $result; } /** * deletes file parts in chunks folder files uploaded * more chunksexpirein seconds ago */ protected function cleanupchunks(){ foreach (scandir($this->chunksfolder) $item){ if ($item == "." || $item == "..") continue; $path = $this->chunksfolder.directory_separator.$item; if (!is_dir($path)) continue; if (time() - filemtime($path) > $this->chunksexpirein){ $this->removedir($path); } } } /** * removes directory , files contained inside * @param string $dir */ protected function removedir($dir){ foreach (scandir($dir) $item){ if ($item == "." || $item == "..") continue; if (is_dir($item)){ $this->removedir($item); } else { unlink(join(directory_separator, array($dir, $item))); } } rmdir($dir); } /** * converts given size units bytes. * @param string $str */ protected function tobytes($str){ $val = trim($str); $last = strtolower($str[strlen($str)-1]); switch($last) { case 'g': $val *= 1024; case 'm': $val *= 1024; case 'k': $val *= 1024; } return $val; } /** * determines whether directory can accessed. * * is_executable() not reliable on windows prior php 5.0.0 * (http://www.php.net/manual/en/function.is-executable.php) * following tests if current os windows , if so, merely * checks if folder writable; * otherwise, checks additionally executable status (like before). * * @param string $directory target directory test access */ protected function isinaccessible($directory) { $iswin = $this->iswindows(); $folderinaccessible = ($iswin) ? !is_writable($directory) : ( !is_writable($directory) && !is_executable($directory) ); return $folderinaccessible; } /** * determines os windows or not * * @return boolean */ protected function iswindows() { $iswin = (strtoupper(substr(php_os, 0, 3)) === 'win'); return $iswin; }
}
thanks in making sure code correct, kicked myself in face one! thinking longest time incorrectly setup apache environment has been root of problems.
i did not have .htaccess setup seemed fix of problems.
here steps followed resolve problem.
first step
open apache.conf file as
sudo vim /etc/apache2/apache2.conf
second step
remove comment sign (#) if find before line ( line number 187 approx.)
accessfilename .htaccess
third step
then find line there is
<directory /var/www/> options indexes followsymlinks allowoverride none require granted </directory>
replace "none" "all"
allowoverride
step 4
activate modrewrite:
sudo a2enmod rewrite sudo service apache2 restart
everything should here.
Comments
Post a Comment