我正在构建一个基于XHR的JavaScript文件上传器。 (事实上,当我使用jQuery时,Ajax) 我使用一些HTML5功能作为Drag& Drop API,以及 - 目前 - FileReader API。
我对这个过程有一些疑问,因为理论上有一些我不理解的东西。
我 - 自愿 - 出于某些原因选择不使用现有的和精心设计的插件 /独立上传者:
我已经阅读了教程Upload Files with Ajax,但我发现奇怪的是使用FileReader API最终将图像附加到FormData API。
除此之外,我真的不想拥有表单,我只是将图像放在一个下拉区域,使用FileReader API获取文件内容,然后将AJAX请求发送到我的服务器。
我只是想知道某人是否有一个更好的流程想法,因为目前:
我不知道如何优化/更快,但看到大图片的时间是愚蠢的,我只是不想通过示例想象它的视频...... 是否可以通过示例仅使用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);
?>