I have my HTML
file:
<html>
<head>
<meta charset="utf-8">
<title>Fine Uploader Demo</title>
<link href="fineuploader-3.4.1.css" rel="stylesheet">
</head>
<body>
<div id="fine-uploader"></div>
<script src="jquery-1.7.2.min.js"></script>
<script src="jquery.fineuploader-3.4.1.js"></script>
<script>
function createUploader() {
var uploader = new qq.FineUploader({
// Pass the HTML element here
element: document.getElementById('fine-uploader'),
// or, if using jQuery
// element: $('#fine-uploader')[0],
// Use the relevant server script url here
// if it's different from the default “/server/upload”
request: {
endpoint: 'qqFileUploader'
}
});
}
window.onload = createUploader;
</script>
</body>
</html>
My PHP Code qqFileUploader.php
<?php
class qqFileUploader {
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; // One week
protected $uploadName;
function __construct(){
$this->sizeLimit = $this->toBytes(ini_get('upload_max_filesize'));
}
/**
* Get the original filename
*/
public function getName(){
if (isset($_REQUEST['qqfilename']))
return $_REQUEST['qqfilename'];
if (isset($_FILES[$this->inputName]))
return $_FILES[$this->inputName]['name'];
}
/**
* Get the name of the uploaded file
*/
public function getUploadName(){
return $this->uploadName;
}
/**
* Process the upload.
* @param string $uploadDirectory Target directory.
* @param string $name Overwrites the name of the 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 that the max upload size specified in class configuration does not
// exceed size allowed by server config
if ($this->toBytes(ini_get('post_max_size')) < $this->sizeLimit ||
$this->toBytes(ini_get('upload_max_filesize')) < $this->sizeLimit){
$size = max(1, $this->sizeLimit / 1024 / 1024) . 'M';
return array('error'=>"Server error. Increase post_max_size and upload_max_filesize to ".$size);
}
// is_writable() is not reliable on Windows (http://www.php.net/manual/en/function.is-executable.php#111146)
// The following tests if the current OS is Windows and if so, merely checks if the folder is writable;
// otherwise, it checks additionally for executable status (like before).
$isWin = (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN');
$folderInaccessible = ($isWin) ? !is_writable($uploadDirectory) : ( !is_writable($uploadDirectory) && !is_executable($uploadDirectory) );
if ($folderInaccessible){
return array('error' => "Server error. Uploads directory isn't writable" . (!$isWin) ? " or executable." : ".");
}
if(!isset($_SERVER['CONTENT_TYPE'])) {
return array('error' => "No files were uploaded.");
} else if (strpos(strtolower($_SERVER['CONTENT_TYPE']), 'multipart/') !== 0){
return array('error' => "Server error. Not a multipart request. Please set forceMultipart to default value (true).");
}
// Get size and name
$file = $_FILES[$this->inputName];
$size = $file['size'];
if ($name === null){
$name = $this->getName();
}
// Validate name
if ($name === null || $name === ''){
return array('error' => 'File name empty.');
}
// Validate file size
if ($size == 0){
return array('error' => 'File is empty.');
}
if ($size > $this->sizeLimit){
return array('error' => 'File is too large.');
}
// 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 an invalid extension, it should be one of '. $these . '.');
}
// Save a chunk
$totalParts = isset($_REQUEST['qqtotalparts']) ? (int)$_REQUEST['qqtotalparts'] : 1;
if ($totalParts > 1){
$chunksFolder = $this->chunksFolder;
$partIndex = (int)$_REQUEST['qqpartindex'];
$uuid = $_REQUEST['qquuid'];
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);
}
$target = $targetFolder.'/'.$partIndex;
$success = move_uploaded_file($_FILES[$this->inputName]['tmp_name'], $target);
// Last chunk saved successfully
if ($success AND ($totalParts-1 == $partIndex)){
$target = $this->getUniqueTargetPath($uploadDirectory, $name);
$this->uploadName = basename($target);
$target = fopen($target, 'wb');
for ($i=0; $i<$totalParts; $i++){
$chunk = fopen($targetFolder.DIRECTORY_SEPARATOR.$i, "rb");
stream_copy_to_stream($chunk, $target);
fclose($chunk);
}
// Success
fclose($target);
for ($i=0; $i<$totalParts; $i++){
unlink($targetFolder.DIRECTORY_SEPARATOR.$i);
}
rmdir($targetFolder);
return array("success" => true);
}
return array("success" => true);
} else {
$target = $this->getUniqueTargetPath($uploadDirectory, $name);
if ($target){
$this->uploadName = basename($target);
if (move_uploaded_file($file['tmp_name'], $target)){
return array('success'=> true);
}
}
return array('error'=> 'Could not save uploaded file.' .
'The upload was cancelled, or server error encountered');
}
}
/**
* Returns a path to use with this upload. Check that the name does not exist,
* and appends a suffix otherwise.
* @param string $uploadDirectory Target directory
* @param string $filename The name of the file to use.
*/
protected function getUniqueTargetPath($uploadDirectory, $filename)
{
// Allow only one process at the time to get a unique file name, otherwise
// if multiple people would upload a file with the same name at the same time
// only the latest would be 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;
// Get unique file name for the file, by 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 an empty target file
if (!touch($result)){
// Failed
$result = false;
}
if (function_exists('sem_acquire')){
sem_release($lock);
}
return $result;
}
/**
* Deletes all file parts in the chunks folder for files uploaded
* more than chunksExpireIn seconds ago
*/
protected function cleanupChunks(){
foreach (scandir($this->chunksFolder) as $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 a directory and all files contained inside
* @param string $dir
*/
protected function removeDir($dir){
foreach (scandir($dir) as $item){
if ($item == "." || $item == "..")
continue;
unlink($dir.DIRECTORY_SEPARATOR.$item);
}
rmdir($dir);
}
/**
* Converts a given size with units to 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;
}
}
When I upload as file, I get the follwing two errors and my file upload fails:
Error 1
OPTIONS file:///C:/Users/upload/qqFileUploader jquery.fineuploader-3.4.1.js:3903
handleStandardFileUpload jquery.fineuploader-3.4.1.js:3903
api.upload jquery.fineuploader-3.4.1.js:3989
upload jquery.fineuploader-3.4.1.js:3041
qq.FineUploaderBasic._upload jquery.fineuploader-3.4.1.js:1437
qq.FineUploaderBasic._uploadFileOrBlobDataList jquery.fineuploader-3.4.1.js:1415
qq.FineUploaderBasic.addFiles jquery.fineuploader-3.4.1.js:1049
qq.FineUploaderBasic._onInputChange jquery.fineuploader-3.4.1.js:1340
qq.UploadButton.onChange jquery.fineuploader-3.4.1.js:1117
(anonymous function) jquery.fineuploader-3.4.1.js:680
Error 2
[FineUploader] Error when attempting to parse xhr response text (SyntaxError: Unexpected end of input) jquery.fineuploader-3.4.1.js:155
qq.log jquery.fineuploader-3.4.1.js:155
qq.FineUploaderBasic.log jquery.fineuploader-3.4.1.js:939
qq.UploadHandler.log jquery.fineuploader-3.4.1.js:1146
parseResponse jquery.fineuploader-3.4.1.js:3683
onComplete jquery.fineuploader-3.4.1.js:3732
(anonymous function) jquery.fineuploader-3.4.1.js:3766
When debug is set to true, I get this:
[FineUploader] xhr - server response received for 0 jquery.fineuploader-3.4.1.js:150
[FineUploader] responseText = <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>404 Not Found</title>
</head><body>
<h1>Not Found</h1>
<p>The requested URL php/qqFileUploader.php was not found on this server.</p>
<hr>
<address>Apache/2.2.15 (CentOS) Server at Port 80</address>
</body></html>