使用jQuery文件上载进行远程上载

时间:2012-11-21 19:00:32

标签: php jquery ajax file-upload

我需要一个远程上传脚本的帮助,该脚本的页面名为' uploadHandler.php'。 我需要使用jQuery PHP文件上载(jQuery文件上载)创建远程上载脚本。我想通过此脚本上传一个来自不同服务器的文件,只输入URL。如何才能做到这一点?

当我请求上传到' uploadHandler.php'它返回

[{"name":"","size":0,"type":null,"error":"File received has zero size."}]

我应该创建哪种表单以确保上传文件?我想从文本框中写的URL上传文件。

代码' uploadHandler.php':

class uploadHandler
{    
    private $options;

    function __construct($options = null)
    {
        // get accepted file types
        $acceptedFileTypes = getAcceptedFileTypes();

        $this->options = array(
            'script_url' => $_SERVER['PHP_SELF'],
            'upload_dir' => _CONFIG_FILE_STORAGE_PATH,
            'upload_url' => dirname($_SERVER['PHP_SELF']) . '/files/',
            'param_name' => 'files',
            'delete_hash' => '',
            // The php.ini settings upload_max_filesize and post_max_size
            // take precedence over the following max_file_size setting:
            'max_file_size' => $this->get_max_upload_size(),
            'min_file_size' => 1,
            'accept_file_types' => COUNT($acceptedFileTypes) ? ('/(\.|\/)(' . str_replace(".", "", implode("|", $acceptedFileTypes)) . ')$/i') : '/.+$/i',
            'max_number_of_files' => null,
            'discard_aborted_uploads' => true,
            'image_versions' => array(
                'thumbnail' => array(
                    'upload_dir' => dirname(__FILE__) . '/thumbnails/',
                    'upload_url' => dirname($_SERVER['PHP_SELF']) . '/thumbnails/',
                    'max_width' => 80,
                    'max_height' => 80
                )
            )
        );
        if ($options)
        {
            $this->options = array_replace_recursive($this->options, $options);
        }
    }

    private function get_max_upload_size()
    {
        // Initialize current user
        $Auth = Auth::getAuth();

        // max allowed upload size
        $maxUploadSize = SITE_CONFIG_FREE_USER_MAX_UPLOAD_FILESIZE;
        if ($Auth->loggedIn())
        {
            // check if user is a premium/paid user
            if ($Auth->level != 'free user')
            {
                $maxUploadSize = SITE_CONFIG_PREMIUM_USER_MAX_UPLOAD_FILESIZE;
            }
        }

        // if php restrictions are lower than permitted, override
        $phpMaxSize = getPHPMaxUpload();
        if ($phpMaxSize < $maxUploadSize)
        {
            $maxUploadSize = $phpMaxSize;
        }

        return $maxUploadSize;
    }

    private function get_file_object($file_name)
    {
        $file_path = $this->options['upload_dir'] . $file_name;
        if (is_file($file_path) && $file_name[0] !== '.')
        {
            $file = new stdClass();
            $file->name = $file_name;
            $file->size = filesize($file_path);
            $file->url = $this->options['upload_url'] . rawurlencode($file->name);
            foreach ($this->options['image_versions'] as $version => $options)
            {
                if (is_file($options['upload_dir'] . $file_name))
                {
                    $file->{$version . '_url'} = $options['upload_url']
                            . rawurlencode($file->name);
                }
            }
            $file->delete_url = '~d?' . $this->options['delete_hash'];
            $file->info_url = '~i?' . $this->options['delete_hash'];
            $file->delete_type = 'DELETE';
            return $file;
        }
        return null;
    }

    private function get_file_objects()
    {
        return array_values(array_filter(array_map(
                                        array($this, 'get_file_object'), scandir($this->options['upload_dir'])
                                )));
    }

    private function create_scaled_image($file_name, $options)
    {
        $file_path = $this->options['upload_dir'] . $file_name;
        $new_file_path = $options['upload_dir'] . $file_name;
        list($img_width, $img_height) = @getimagesize($file_path);
        if (!$img_width || !$img_height)
        {
            return false;
        }
        $scale = min(
                $options['max_width'] / $img_width, $options['max_height'] / $img_height
        );
        if ($scale > 1)
        {
            $scale = 1;
        }
        $new_width = $img_width * $scale;
        $new_height = $img_height * $scale;
        $new_img = @imagecreatetruecolor($new_width, $new_height);
        switch (strtolower(substr(strrchr($file_name, '.'), 1)))
        {
            case 'jpg':
            case 'jpeg':
                $src_img = @imagecreatefromjpeg($file_path);
                $write_image = 'imagejpeg';
                break;
            case 'gif':
                $src_img = @imagecreatefromgif($file_path);
                $write_image = 'imagegif';
                break;
            case 'png':
                $src_img = @imagecreatefrompng($file_path);
                $write_image = 'imagepng';
                break;
            default:
                $src_img = $image_method = null;
        }
        $success = $src_img && @imagecopyresampled(
                        $new_img, $src_img, 0, 0, 0, 0, $new_width, $new_height, $img_width, $img_height
                ) && $write_image($new_img, $new_file_path);
        // Free up memory (imagedestroy does not delete files):
        @imagedestroy($src_img);
        @imagedestroy($new_img);
        return $success;
    }

    private function has_error($uploaded_file, $file, $error)
    {
        if ($error)
        {
            return $error;
        }
        if (!preg_match($this->options['accept_file_types'], $file->name))
        {
            return 'acceptFileTypes';
        }
        if ($uploaded_file && is_uploaded_file($uploaded_file))
        {
            $file_size = filesize($uploaded_file);
        } else
        {
            $file_size = $_SERVER['CONTENT_LENGTH'];
        }
        if ($this->options['max_file_size'] && (
                $file_size > $this->options['max_file_size'] ||
                $file->size > $this->options['max_file_size'])
        )
        {
            return 'maxFileSize';
        }
        if ($this->options['min_file_size'] &&
                $file_size < $this->options['min_file_size'])
        {
            return 'minFileSize';
        }
        if (is_int($this->options['max_number_of_files']) && (
                count($this->get_file_objects()) >= $this->options['max_number_of_files'])
        )
        {
            return 'maxNumberOfFiles';
        }
        return $error;
    }

    private function handle_file_upload($uploaded_file, $name, $size, $type, $error)
    {
        $fileUpload = new stdClass();
        $fileUpload->name = basename(stripslashes($name));
        $fileUpload->size = intval($size);
        $fileUpload->type = $type;
        $fileUpload->error = null;

        $extension = end(explode(".", $fileUpload->name));
        $fileUpload->error = $this->has_error($uploaded_file, $fileUpload, $error);
        if (!$fileUpload->error)
        {
            if (strlen(trim($fileUpload->name)) == 0)
            {
                $fileUpload->error = 'Filename not found.';
            }
        }
        elseif (intval($size) == 0)
        {
            $fileUpload->error = 'File received has zero size.';
        }
        elseif (intval($size) > $this->options['max_file_size'])
        {
            $fileUpload->error = 'File received is larger than permitted.';
        }

        if (!$fileUpload->error && $fileUpload->name)
        {
            if ($fileUpload->name[0] === '.')
            {
                $fileUpload->name = substr($fileUpload->name, 1);
            }
            $newFilename = MD5(microtime());

            // figure out upload type
            $file_size = 0;

            // select server from pool
            $uploadServerId = getAvailableServerId();
            $db = Database::getDatabase(true);
            $uploadServerDetails = $db->getRow('SELECT * FROM file_server WHERE id = ' . $db->quote($uploadServerId));

            // override storage path
            if(strlen($uploadServerDetails['storagePath']))
            {
                $this->options['upload_dir'] = $uploadServerDetails['storagePath'];
                if (substr($this->options['upload_dir'], strlen($this->options['upload_dir']) - 1, 1) == '/')
                {
                    $this->options['upload_dir'] = substr($this->options['upload_dir'], 0, strlen($this->options['upload_dir']) - 1);
                }
                $this->options['upload_dir'] .= '/';
            }

            // move remotely via ftp
            if($uploadServerDetails['serverType'] == 'remote')
            {
                // connect ftp
                $conn_id = ftp_connect($uploadServerDetails['ipAddress'], $uploadServerDetails['ftpPort'], 30);
                if($conn_id === false)
                {
                    $fileUpload->error = 'Could not connect to file server '.$uploadServerDetails['ipAddress'];
                }

                // authenticate
                if(!$fileUpload->error)
                {
                    $login_result = ftp_login($conn_id, $uploadServerDetails['ftpUsername'], $uploadServerDetails['ftpPassword']);
                    if($login_result === false)
                    {
                        $fileUpload->error = 'Could not authenticate with file server '.$uploadServerDetails['ipAddress'];
                    }
                }

                // create the upload folder
                if(!$fileUpload->error)
                {
                    $uploadPathDir = $this->options['upload_dir'] . substr($newFilename, 0, 2);
                    if(!ftp_mkdir($conn_id, $uploadPathDir))
                    {
                        // Error reporting removed for now as it causes issues with existing folders. Need to add a check in before here
                        // to see if the folder exists, then create if not.
                        // $fileUpload->error = 'There was a problem creating the storage folder on '.$uploadServerDetails['ipAddress'];
                    }
                }

                // upload via ftp
                if(!$fileUpload->error)
                {
                    $file_path = $uploadPathDir . '/' . $newFilename;
                    clearstatcache();
                    if ($uploaded_file && is_uploaded_file($uploaded_file))
                    {
                        // initiate ftp
                        $ret = ftp_nb_put($conn_id, $file_path, $uploaded_file, 
                                            FTP_BINARY, FTP_AUTORESUME);
                        while ($ret == FTP_MOREDATA)
                        {
                            // continue uploading
                            $ret = ftp_nb_continue($conn_id);
                        }

                        if ($ret != FTP_FINISHED)
                        {
                            $fileUpload->error = 'There was a problem uploading the file to '.$uploadServerDetails['ipAddress'];
                        }
                        else
                        {
                            $file_size = filesize($uploaded_file);
                            @unlink($uploaded_file);
                        }
                    }
                }

                // close ftp connection
                ftp_close($conn_id);
            }
            // move into local storage
            else
            {
                // create the upload folder
                $uploadPathDir = $this->options['upload_dir'] . substr($newFilename, 0, 2);
                @mkdir($uploadPathDir);

                $file_path = $uploadPathDir . '/' . $newFilename;
                clearstatcache();
                if ($uploaded_file && is_uploaded_file($uploaded_file))
                {
                    move_uploaded_file($uploaded_file, $file_path);
                }
                $file_size = filesize($file_path);
            }

            // check filesize uploaded matches tmp uploaded
            if ($file_size === $fileUpload->size)
            {
                $fileUpload->url = $this->options['upload_url'] . rawurlencode($fileUpload->name);

                // insert into the db
                $fileUpload->size = $file_size;
                $fileUpload->delete_url = '~d?' . $this->options['delete_hash'];
                $fileUpload->info_url = '~i?' . $this->options['delete_hash'];
                $fileUpload->delete_type = 'DELETE';

                // create delete hash, make sure it's unique
                $deleteHash = md5($fileUpload->name . getUsersIPAddress() . microtime());
                $existingFile = file::loadByDeleteHash($deleteHash);
                while ($existingFile != false)
                {
                    $deleteHash = md5($fileUpload->name . getUsersIPAddress() . microtime());
                    $existingFile = file::loadByDeleteHash($deleteHash);
                }

                // store in db
                $db = Database::getDatabase(true);
                $dbInsert = new DBObject("file", array("originalFilename", "shortUrl", "fileType", "extension", "fileSize", "localFilePath", "userId", "totalDownload", "uploadedIP", "uploadedDate", "statusId", "deleteHash", "serverId"));

                $dbInsert->originalFilename = $fileUpload->name;
                $dbInsert->shortUrl = 'temp';
                $dbInsert->fileType = $fileUpload->type;
                $dbInsert->extension = $extension;
                $dbInsert->fileSize = $fileUpload->size;
                $dbInsert->localFilePath = str_replace($this->options['upload_dir'], "", $file_path);

                // add user id if user is logged in
                $dbInsert->userId = NULL;
                $Auth = Auth::getAuth();
                if ($Auth->loggedIn())
                {
                    $dbInsert->userId = (int) $Auth->id;
                }

                $dbInsert->totalDownload = 0;
                $dbInsert->uploadedIP = getUsersIPAddress();
                $dbInsert->uploadedDate = sqlDateTime();
                $dbInsert->statusId = 1;
                $dbInsert->deleteHash = $deleteHash;
                $dbInsert->serverId = $uploadServerId;

                if (!$dbInsert->insert())
                {
                    $fileUpload->error = 'abort';
                }

                // create short url
                $tracker = 1;
                $shortUrl = file::createShortUrlPart($tracker . $dbInsert->id);
                $fileTmp = file::loadByShortUrl($shortUrl);
                while ($fileTmp)
                {
                    $shortUrl = file::createShortUrlPart($tracker . $dbInsert->id);
                    $fileTmp = file::loadByShortUrl($shortUrl);
                    $tracker++;
                }

                // update short url
                file::updateShortUrl($dbInsert->id, $shortUrl);

                // update fileUpload with file location
                $file = file::loadByShortUrl($shortUrl);
                $fileUpload->url = $file->getFullShortUrl();
                $fileUpload->delete_url = $file->getDeleteUrl();
                $fileUpload->info_url = $file->getInfoUrl();
                $fileUpload->stats_url = $file->getStatisticsUrl();
                $fileUpload->short_url = $shortUrl;
            }
            else if ($this->options['discard_aborted_uploads'])
            {
                //@TODO - made ftp compatible
                @unlink($file_path);
                @unlink($uploaded_file);
                if(!isset($fileUpload->error))
                {
                    $fileUpload->error = 'maxFileSize';
                }
            }
        }

        return $fileUpload;
    }

    public function get()
    {
        $file_name = isset($_REQUEST['file']) ?
                basename(stripslashes($_REQUEST['file'])) : null;
        if ($file_name)
        {
            $info = $this->get_file_object($file_name);
        } else
        {
            $info = $this->get_file_objects();
        }
        header('Content-type: application/json');
        echo json_encode($info);
    }

    public function post()
    {
        $upload = isset($_FILES[$this->options['param_name']]) ?
                $_FILES[$this->options['param_name']] : array(
            'tmp_name' => null,
            'name' => null,
            'size' => null,
            'type' => null,
            'error' => null
                );
        $info = array();
        if (is_array($upload['tmp_name']))
        {
            foreach ($upload['tmp_name'] as $index => $value)
            {
                $info[] = $this->handle_file_upload($upload['tmp_name'][$index], 
                        isset($_SERVER['HTTP_X_FILE_NAME']) ? $_SERVER['HTTP_X_FILE_NAME'] : $upload['name'][$index], 
                        isset($_SERVER['HTTP_X_FILE_SIZE']) ? $_SERVER['HTTP_X_FILE_SIZE'] : $upload['size'][$index], 
                        isset($_SERVER['HTTP_X_FILE_TYPE']) ? $_SERVER['HTTP_X_FILE_TYPE'] : $upload['type'][$index], 
                        $upload['error'][$index]
                );
            }
        } else
        {
            $info[] = $this->handle_file_upload($upload['tmp_name'], 
                    isset($_SERVER['HTTP_X_FILE_NAME']) ? $_SERVER['HTTP_X_FILE_NAME'] : $upload['name'],
                    isset($_SERVER['HTTP_X_FILE_SIZE']) ? $_SERVER['HTTP_X_FILE_SIZE'] : $upload['size'],
                    isset($_SERVER['HTTP_X_FILE_TYPE']) ? $_SERVER['HTTP_X_FILE_TYPE'] : $upload['type'],
                    $upload['error']
            );
        }
        header('Vary: Accept');
        if (isset($_SERVER['HTTP_ACCEPT']) &&
                (strpos($_SERVER['HTTP_ACCEPT'], 'application/json') !== false))
        {
            header('Content-type: application/json');
        } else
        {
            header('Content-type: text/plain');
        }
        echo json_encode($info);
    }

}

$upload_handler = new uploadHandler();

header('Pragma: no-cache');
header('Cache-Control: private, no-cache');
header('Content-Disposition: inline; filename="files.json"');

// check we are receiving the request from this script
if (!checkReferrer())
{
    // exit
    header('HTTP/1.0 400 Bad Request');
    exit();
}

switch ($_SERVER['REQUEST_METHOD'])
{
    case 'HEAD':
    case 'GET':
        $upload_handler->get();
        break;
    case 'POST':
        $upload_handler->post();
        break;
    default:
        header('HTTP/1.0 405 Method Not Allowed');
}

文件_indexJS.php:

var fileUrls = [];
var lastEle = null;
var startTime = null;
$(document).ready(function() {
    'use strict';

    // Initialize the jQuery File Upload widget:
    $('#fileupload').fileupload({
        sequentialUploads: true,
        maxFileSize: <?php echo $maxUploadSize; ?>,
        <?php echo COUNT($acceptedFileTypes)?('acceptFileTypes: /(\\.|\\/)('.str_replace(".", "", implode("|", $acceptedFileTypes).')$/i,')):''; ?> maxNumberOfFiles: 50
    })
    .bind('fileuploadadd', function(e, data) {
        $('#fileupload #fileListingWrapper').removeClass('hidden');
        $('#fileupload #initialUploadSection').addClass('hidden');
        $('#fileUploadBadge').addClass('hidden');

        // fix for safari
        getTotalRows();
        // end safari fix

        totalRows = getTotalRows()+1;
        updateTotalFilesText(totalRows);

    })
    .bind('fileuploadstart', function(e, data) {
        // hide/show sections
        $('#addFileRow').addClass('hidden');
        $('#processQueueSection').addClass('hidden');
        $('#processingQueueSection').removeClass('hidden');

        // set all cancel icons to processing
        $('.cancel').html('<img class="processingIcon" src="<?php echo SITE_IMAGE_PATH; ?>/processing_small.gif" width="16" height="16"/>');

        // set timer
        startTime = (new Date()).getTime();
    })
    .bind('fileuploadstop', function(e, data) {
        // finished uploading
        updateTitleWithProgress(100);
        updateProgessText(100, data.total, data.total);
        $('#processQueueSection').addClass('hidden');
        $('#processingQueueSection').addClass('hidden');
        $('#completedSection').removeClass('hidden');

        // set all remainging pending icons to failed
        $('.processingIcon').parent().html('<img src="<?php echo SITE_IMAGE_PATH; ?>/red_error_small.png" width="16" height="16"/>');

        // setup copy link
        setupCopyAllLink();
    })
    .bind('fileuploadprogressall', function(e, data) {
        // update page title with progress
        var progress = parseInt(data.loaded / data.total * 100, 10);
        updateTitleWithProgress(progress);
        updateProgessText(progress, data.loaded, data.total);
    })
    .bind('fileuploaddone', function(e, data) {
        // keep a copy of the urls globally
        fileUrls.push(data['result'][0]['url']);
    })
    .bind('fileuploadfail', function(e, data) {
        totalRows = getTotalRows();
        if(totalRows > 0)
        {
            totalRows = totalRows-1;
        }

        // if no items, show the original uploader
        if(totalRows == 0)
        {
            $('#fileupload #initialUploadSection').removeClass('hidden');
            $('#fileupload #fileListingWrapper').addClass('hidden');
            $('#fileUploadBadge').removeClass('hidden');
        }
        else
        {
            updateTotalFilesText(totalRows);
        }
    });

    // Open download dialogs via iframes,
    // to prevent aborting current uploads:
    $('#fileupload #files a:not([target^=_blank])').live('click', function (e) {
        e.preventDefault();
        $('<iframe style="display:none;"></iframe>')
            .prop('src', this.href)
            .appendTo('body');
    });

    //$(".ui-dialog-buttonpane").html("<div class='btn_bar_left'><div class='fileupload-progressbar'></div></div>"+$(".ui-dialog-buttonpane").html());
});

function setupCopyAllLink()
{
    // setup copy to clipboard
    $('#copyAllLink').zclip({
        path: "js/ZeroClipboard.swf",
        copy: getUrlsAsText()
    });
}

function updateProgessText(progress, uploadedBytes, totalBytes)
{
    // calculate speed & time left
    nowTime = (new Date()).getTime();
    loadTime = (nowTime - startTime);
    if(loadTime == 0)
    {
        loadTime = 1;
    }
    loadTimeInSec = loadTime/1000;
    bytesPerSec = uploadedBytes / loadTimeInSec;

    textContent = '';
    textContent += 'Progress: '+progress+'%';
    textContent += ' ';
    textContent += '('+bytesToSize(uploadedBytes, 1)+' / '+bytesToSize(totalBytes, 1)+')';

    $("#fileupload-progresstextLeft").html(textContent);

    rightTextContent = '';
    rightTextContent += 'Speed: '+bytesToSize(bytesPerSec, 1)+'ps. ';
    rightTextContent += 'Remaining: '+humanReadableTime((totalBytes/bytesPerSec)-(uploadedBytes/bytesPerSec));

    $("#fileupload-progresstextRight").html(rightTextContent);
}

function getUrlsAsText()
{
    urlStr = '';
    for(var i=0; i<fileUrls.length; i++)
    {
        urlStr += fileUrls[i]+'\n';
    }

    return urlStr;
}

function updateTitleWithProgress(progress)
{
    if(typeof(progress) == "undefined")
    {
        var progress = 0;
    }
    if(progress == 0)
    {
        $(document).attr("title", "<?php echo PAGE_NAME; ?> - <?php echo SITE_CONFIG_SITE_NAME; ?>");
    }
    else
    {
        $(document).attr("title", progress+"% Uploaded - <?php echo PAGE_NAME; ?> - <?php echo SITE_CONFIG_SITE_NAME; ?>");
    }
}

function getTotalRows()
{
    totalRows = $('#files .template-upload').length;
    if(typeof(totalRows) == "undefined")
    {
        return 0;
    }

    return totalRows;
}

function updateTotalFilesText(total)
{
    // removed for now, might be useful in some form in the future
    //$('#uploadButton').html('upload '+total+' files');
}

function setRowClasses()
{
    // removed for now, might be useful in some form in the future
    //$('#files tr').removeClass('even');
    //$('#files tr').removeClass('odd');
    //$('#files tr:even').addClass('odd');
    //$('#files tr:odd').addClass('even');
}

function showAdditionalInformation(ele)
{
    // block parent clicks from being processed on additional information
    $('.sliderContent table').unbind();
    $('.sliderContent table').click(function(e){
        e.stopPropagation();
    });

    // make sure we've clicked on a new element
    if(lastEle == ele)
    {
        // close any open sliders
        $('.sliderContent').slideUp('fast');
        // remove row highlighting
        $('.sliderContent').parent().parent().removeClass('rowSelected');
        lastEle = null;
        return false;
    }
    lastEle = ele;

    // close any open sliders
    $('.sliderContent').slideUp('fast');

    // remove row highlighting
    $('.sliderContent').parent().parent().removeClass('rowSelected');

    // select row and popup content
    $(ele).addClass('rowSelected');

    // set the position of the sliderContent div
    $(ele).find('.sliderContent').css('left', $(ele).offset().left);
    $(ele).find('.sliderContent').css('top', $(ele).offset().top+38);
    $(ele).find('.sliderContent').slideDown(400, function() {
    });

    return false;
}

function saveFileToFolder(ele)
{
    // get variables
    shortUrl = $(ele).closest('.sliderContent').children('.shortUrlHidden').val();
    folderId = $(ele).val();

    // send ajax request
    var request = $.ajax({
        url: "<?php echo _CONFIG_SITE_PROTOCOL . '://' . _CONFIG_SITE_FULL_URL; ?>/_updateFolder.ajax.php",
        type: "POST",
        data: {shortUrl: shortUrl, folderId: folderId},
        dataType: "html"
    });
}

0 个答案:

没有答案