javascript - mostrar - load jquery
Uso de cargas de archivos HTML5 con AJAX y jQuery (2)
Es cierto que hay preguntas similares en Stack Overflow, pero parece que ninguna cumple con mis requisitos.
Esto es lo que estoy buscando hacer:
- Suba una forma completa de datos, una parte de la cual es un solo archivo
- Trabajar con la biblioteca de carga de archivos de Codeigniter
Hasta aquí, todo está bien. Los datos entran en mi base de datos cuando lo necesito. Pero también me gustaría enviar mi formulario a través de una publicación de AJAX:
- Uso de la API de archivos HTML5 nativa, no flash o una solución iframe
- Preferiblemente interactuando con el método jQuery de
.ajax()
bajo nivel
Creo que puedo imaginarme cómo hacerlo cargando automáticamente el archivo cuando el valor del campo cambia usando javascript puro, pero prefiero hacerlo todo de una sola vez para enviarlo en jQuery. Estoy pensando que no es posible hacerlo a través de cadenas de consulta ya que necesito pasar todo el objeto de archivo, pero estoy un poco perdido sobre qué hacer en este momento.
¿Se puede lograr esto?
Con jQuery (y sin la API FormData) puede usar algo como esto:
function readFile(file){
var loader = new FileReader();
var def = $.Deferred(), promise = def.promise();
//--- provide classic deferred interface
loader.onload = function (e) { def.resolve(e.target.result); };
loader.onprogress = loader.onloadstart = function (e) { def.notify(e); };
loader.onerror = loader.onabort = function (e) { def.reject(e); };
promise.abort = function () { return loader.abort.apply(loader, arguments); };
loader.readAsBinaryString(file);
return promise;
}
function upload(url, data){
var def = $.Deferred(), promise = def.promise();
var mul = buildMultipart(data);
var req = $.ajax({
url: url,
data: mul.data,
processData: false,
type: "post",
async: true,
contentType: "multipart/form-data; boundary="+mul.bound,
xhr: function() {
var xhr = jQuery.ajaxSettings.xhr();
if (xhr.upload) {
xhr.upload.addEventListener(''progress'', function(event) {
var percent = 0;
var position = event.loaded || event.position; /*event.position is deprecated*/
var total = event.total;
if (event.lengthComputable) {
percent = Math.ceil(position / total * 100);
def.notify(percent);
}
}, false);
}
return xhr;
}
});
req.done(function(){ def.resolve.apply(def, arguments); })
.fail(function(){ def.reject.apply(def, arguments); });
promise.abort = function(){ return req.abort.apply(req, arguments); }
return promise;
}
var buildMultipart = function(data){
var key, crunks = [], bound = false;
while (!bound) {
bound = $.md5 ? $.md5(new Date().valueOf()) : (new Date().valueOf());
for (key in data) if (~data[key].indexOf(bound)) { bound = false; continue; }
}
for (var key = 0, l = data.length; key < l; key++){
if (typeof(data[key].value) !== "string") {
crunks.push("--"+bound+"/r/n"+
"Content-Disposition: form-data; name=/""+data[key].name+"/"; filename=/""+data[key].value[1]+"/"/r/n"+
"Content-Type: application/octet-stream/r/n"+
"Content-Transfer-Encoding: binary/r/n/r/n"+
data[key].value[0]);
}else{
crunks.push("--"+bound+"/r/n"+
"Content-Disposition: form-data; name=/""+data[key].name+"/"/r/n/r/n"+
data[key].value);
}
}
return {
bound: bound,
data: crunks.join("/r/n")+"/r/n--"+bound+"--"
};
};
//----------
//---------- On submit form:
var form = $("form");
var $file = form.find("#file");
readFile($file[0].files[0]).done(function(fileData){
var formData = form.find(":input:not(''#file'')").serializeArray();
formData.file = [fileData, $file[0].files[0].name];
upload(form.attr("action"), formData).done(function(){ alert("successfully uploaded!"); });
});
Con la API de FormData solo tienes que agregar todos los campos de tu formulario al objeto FormData y enviarlo a través de $ .ajax ({url: url, data: formData, processData: false, contentType: false, escribe: "POST"})
No es muy difícil. En primer lugar, eche un vistazo a la interfaz FileReader .
Entonces, cuando se envíe el formulario, tome el proceso de envío y
var file = document.getElementById(''fileBox'').files[0]; //Files[0] = 1st file
var reader = new FileReader();
reader.readAsText(file, ''UTF-8'');
reader.onload = shipOff;
//reader.onloadstart = ...
//reader.onprogress = ... <-- Allows you to update a progress bar.
//reader.onabort = ...
//reader.onerror = ...
//reader.onloadend = ...
function shipOff(event) {
var result = event.target.result;
var fileName = document.getElementById(''fileBox'').files[0].name; //Should be ''picture.jpg''
$.post(''/myscript.php'', { data: result, name: fileName }, continueSubmission);
}
Luego, en el lado del servidor (es decir, myscript.php):
$data = $_POST[''data''];
$fileName = $_POST[''name''];
$serverFile = time().$fileName;
$fp = fopen(''/uploads/''.$serverFile,''w''); //Prepends timestamp to prevent overwriting
fwrite($fp, $data);
fclose($fp);
$returnData = array( "serverFile" => $serverFile );
echo json_encode($returnData);
O algo así. Puedo estar equivocado (y si lo estoy, por favor, corregirme), pero esto debería almacenar el archivo como algo como 1287916771myPicture.jpg
in /uploads/
1287916771myPicture.jpg
/uploads/
en su servidor, y responder con una variable JSON (a una función continueSubmission()
) que contiene el nombre de archivo en el servidor.
Echa un vistazo a fwrite()
y jQuery.post()
.
En la página anterior se detalla cómo usar readAsBinaryString()
, readAsDataUrl()
y readAsArrayBuffer()
para sus otras necesidades (por ejemplo, imágenes, videos, etc.).