上传程序/良好实践 - FileReader?

时间:2013-03-06 12:10:49

标签: javascript html5 filereader asyncfileupload

我正在构建一个基于XHR的JavaScript文件上传器。 (事实上​​,当我使用jQuery时,Ajax) 我使用一些HTML5功能作为Drag& Drop API,以及 - 目前 - FileReader API。

我对这个过程有一些疑问,因为理论上有一些我不理解的东西。

我 - 自愿 - 出于某些原因选择不使用现有的和精心设计的插件 /独立上传者:

  • 我有一些特定的需求,例如在项目
  • 中添加标题和描述(如在facebook中)
  • 我会自己实现它作为HTML5 API的尝试。

我已经阅读了教程Upload Files with Ajax,但我发现奇怪的是使用FileReader API最终将图像附加到FormData API。

除此之外,我真的不想拥有表单,我只是将图像放在一个下拉区域,使用FileReader API获取文件内容,然后将AJAX请求发送到我的服务器。

我只是想知道某人是否有一个更好的流程想法,因为目前:

  1. 我获取了删除的文件并读取了它的内容(异步,但需要一些时间......)
  2. 我通过AJAX请求将此内容发送到服务器
  3. 我将内容写入服务器上的物理文件(再花些时间)
  4. 我不知道如何优化/更快,但看到大图片的时间是愚蠢的,我只是不想通过示例想象它的视频...... 是否可以通过示例仅使用Ajax发送文件的引用,并直接管理上载,而不是获取文件内容然后等待用户单击发送按钮发送它?

    例如,Facebook上传器如何工作,他们似乎解决了问题/使用某些东西来修复它?

    (如果有人有兴趣了解或看一看,这里有一小部分我现在所做的事情)

    /* HTML */
    <div id='drop-area'>
        <h3 class='placeholder'>Drop your files there!</h3>
    </div>
    
    /* CSS */
    #drop-area {
        position: relative;
        width: 100%;
        height: 400px;
        border: 1px dashed grey;
        border-radius: 10px;
    }
    #drop-area.drag-over {
        border: 1px solid cyan;
    }
    #drop-area .placeholder {
        position: absolute;
        top: 50%;
        left: 50%;
        width: 235px;
        height: 25px;
        margin: -12px 0 0 -117px;
        line-height: 25px;
        text-transform: uppercase;
    }
    
    /* JavaScript - jQuery way */
    // This code is NOT AT ALL full-browser compatible !!
    $(document).ready(function () {
        var i,
            $dropArea = $('drop-area'),
            fileReader,
            file,
            result,
            sendRequest = function () {
                $.ajax({
                    url: 'upload.php',
                    type: 'post',
                    data: {
                        title: $('#title').val(),
                        description: $('#description').val(),
                        data: result, // base64 encoded data
                        type: file.type
                    },
                    processData: false, // No query string
                    contentType: false // No data formatting
                }).fail(function (error, status) {
                    console.log(error, status);
                    alert('Fail...');
                }).done(function (response, output) {
                    console.log(response, output);
                    alert('Uploaded!');
                }).always(function () {
                    $('#file-form-container').empty().detach();
                });
            },
            onFileFormSubmit = function (e) {
                e.preventDefault();
                sendRequest();
                return false;
            },
            displayForm = function (data) {
                $('body').append($('<div/>', {
                    'id': 'file-form-container'
                }).append($('<form/>', {
                    'action': '#',
                    'id': 'file-form'
                }).append($('<img/>', {
                    'src': data,
                    'alt': 'File',
                    'width': 100px
                })).append($('<input/>', {
                    'id': 'title',
                    'type': 'text',
                    'name': 'title'
                })).append($('<textarea/>', {
                    'id': 'description',
                    'class': 'description',
                    'name': 'description'
                })).append($('<input/>', {
                    'type': 'submit',
                    'name': 'submit',
                    'value': 'Send!'
                }))));
            },
            onProgress = function (e) {
                console.log('progress', e);
                // Update a <progress> element...
            },
            onLoadEnd = function (e) {
                console.log('load end', e);
                result = e.target.result;
                displayForm(result);
            },
            onError = function (e) {
                console.log('error', e);
                // Display a message...
            }
            readFile = function (file) {
                fileReader = new FileReader();
                fileReader.onprogress = onProgress;
                fileReader.onerror = onError;
                fileReader.onloadend = onLoadEnd;
                fileReader.readAsDataURL(file);
            };
    
        $dropArea.on('dragenter', function (e) {
            $(this).addClass('drag-over');
        }).on('dragover', function (e) {
            e.preventDefault();
            e.originalEvent.dataTransfer.dropEffect = 'copy'; // Check the browser support if you want to fix the compatibility
        }).on('dragleave', function (e) {
            e.preventDefault();
            $(this).removeClass('drag-over');
        }).on('dragend', function (e) {
            e.preventDefault();
            $(this).removeClass('drag-over');
        }).on('drop', function (e) {
            // e || e.originalEvent ?
            e.preventDefault();
            e.stopPropagation();
            $(this).removeClass('drag-over');
    
            if (e.originalEvent.dataTransfer.files) {
                for (i = 0, i < e.originalEvent.dataTransfer.files.length; i++) {
                    // Work with arrays to manage multiple files
                    file = e.originalEvent.dataTransfer.files[i];
                    readFile(file); // Read the file content then process the upload (callbacks)
                }
            }
        })
    });
    
    /* PHP - Symfony2 */
    <?php
    
    // Symfony 2 Controller Context
    
    $em = $this->getDoctrine()->getEntityManager();
    
    // get params
    $request = $this->getRequest();
    
    // Check for types, sizes, errors etc.
    if ($request->get('data') && [...]) {
        [...]
    }
    
    // write the decoded data into a file
    // fwrite(base64_decode(...));
    // By the way, is there any OOP - MVC way to do that with Symfony2 ?
    $path = ''; // define the file path
    
    
    // Save the entity
    $entity = new Picture();
    $entity->setTitle($request->get('title'));
    $entity->setDescription($request->get('description'));
    $entity->setPath($path);
    $em->persist($entity);
    $em->flush();
    
    return new JsonResponse(array($entity), 202);
    
    ?>
    

0 个答案:

没有答案