javascript - multiple - maxFileSize y acceptFileTypes en el complemento de carga de archivos blueimp no funcionan. ¿Por qué?
jquery fileupload js (13)
Estoy usando el complemento de carga de archivos BlueQuery jQuery para subir archivos.
No tuve ningún problema para cargar, pero la opción maxFileSize
y acceptFileTypes
no funcionan.
Este es mi código:
$(document).ready(function () {
''use strict'';
$(''#fileupload'').fileupload({
dataType: ''json'',
autoUpload: false,
acceptFileTypes: /(/.|//)(gif|jpe?g|png)$/i,
maxFileSize: 5000000,
done: function (e, data) {
$.each(data.result.files, function (index, file) {
$(''<p style="color: green;">'' + file.name + ''<i class="elusive-ok" style="padding-left:10px;"/> - Type: '' + file.type + '' - Size: '' + file.size + '' byte</p>'')
.appendTo(''#div_files'');
});
},
fail: function (e, data) {
$.each(data.messages, function (index, error) {
$(''<p style="color: red;">Upload file error: '' + error + ''<i class="elusive-remove" style="padding-left:10px;"/></p>'')
.appendTo(''#div_files'');
});
},
progressall: function (e, data) {
var progress = parseInt(data.loaded / data.total * 100, 10);
$(''#progress .bar'').css(''width'', progress + ''%'');
}
});
});
Como se sugirió en una respuesta anterior, necesitamos incluir dos archivos adicionales: jquery.fileupload-process.js
y luego jquery.fileupload-validate.js
Sin embargo, como necesito realizar algunas llamadas ajax adicionales mientras agrego un archivo, me suscribo a el evento fileuploadadd
para realizar esas llamadas. Con respecto a dicho uso, el autor de este complemento sugirió lo siguiente
Por favor, eche un vistazo aquí: https://github.com/blueimp/jQuery-File-Upload/wiki/Options#wiki-callback-options
Agregar oyentes de eventos adicionales a través del método bind (o en el método con jQuery 1.7+) es la opción preferida para conservar la configuración de devolución de llamada mediante la versión de la IU de carga de archivos jQuery.
Alternativamente, también puede simplemente iniciar el procesamiento en su devolución de llamada, así: https://github.com/blueimp/jQuery-File-Upload/blob/master/js/jquery.fileupload-process.js#L50
Usando la combinación de las dos opciones sugeridas, el siguiente código funciona perfectamente para mí
$fileInput.fileupload({
url: ''upload_url'',
type: ''POST'',
dataType: ''json'',
autoUpload: false,
disableValidation: false,
maxFileSize: 1024 * 1024,
messages: {
maxFileSize: ''File exceeds maximum allowed size of 1MB'',
}
});
$fileInput.on(''fileuploadadd'', function(evt, data) {
var $this = $(this);
var validation = data.process(function () {
return $this.fileupload(''process'', data);
});
validation.done(function() {
makeAjaxCall(''some_other_url'', { fileName: data.files[0].name, fileSizeInBytes: data.files[0].size })
.done(function(resp) {
data.formData = data.formData || {};
data.formData.someData = resp.SomeData;
data.submit();
});
});
validation.fail(function(data) {
console.log(''Upload error: '' + data.files[0].error);
});
});
Debe incluir jquery.fileupload-process.js y jquery.fileupload-validate.js para que funcione.
Debe incluir jquery.fileupload-process.js y jquery.fileupload-validate.js para que funcione.
Entonces...
$(this).fileupload({
// ...
processfail: function (e, data) {
data.files.forEach(function(file){
if (file.error) {
self.$errorMessage.html(file.error);
return false;
}
});
},
//...
}
La devolución de llamada processfail se inicia después de una falla de validación.
Ejemplo comprobado / válido para:
- entradas de archivos múltiples
- para uno o
$.grep()
archivos subir -$.grep()
para eliminar archivos de la matriz con errores -
image
y formato deaudio
- tipos de archivos dinámicos desde cadena por
new RegExp()
Aviso: acceptFileTypes.test()
- verifica los tipos de mime, para el archivo adio como .mp3
será audio/mpeg
- no solo la extensión. Para todas las opciones de blueimp: https://github.com/blueimp/jQuery-File-Upload/wiki/Options
$(''input[type="file"]'').each(function(i){
// .form_files is my div/section of form for input file and progressbar
var $progressbar = $(this).parents(''.form_files:first'').find(''.progress-bar:first'');
var $image_format = ''jpg|jpeg|jpe|png|gif'';
var $audio_format = ''mp3|mpeg'';
var $all_formats = $image_format + ''|'' + $audio_format;
var $image_size = 2;
var $audio_size = 10;
var mb = 1048576;
$(this).fileupload({
// ...
singleFileUploads: false, // << send all together, not single
// ...
add: function (e, data) {
// array with all indexes of files with errors
var error_uploads_indexes = [];
// when add file - each file
$.each(data.files, function(index, file) {
// array for all errors
var uploadErrors = [];
// validate all formats first
if($all_formats){
// check all formats first - before size
var acceptFileTypes = "(/.|//)(" + $all_formats + ")$";
acceptFileTypes = new RegExp(acceptFileTypes, "i");
// when wrong format
if(data.files[index][''type''].length && !acceptFileTypes.test(data.files[index][''type''])) {
uploadErrors.push(''Not an accepted file type'');
}else{
// default size is image_size
var $my_size = $image_size;
// check audio format
var acceptFileTypes = "(/.|//)(" + $audio_format + ")$";
acceptFileTypes = new RegExp(acceptFileTypes, "i");
// alert(data.files[index][''type'']);
// alert(acceptFileTypes.test(''audio/mpeg''));
// if is audio then size is audio_size
if(data.files[index][''type''].length && acceptFileTypes.test(data.files[index][''type''])) {
$my_size = $audio_size;
}
// check size
if(data.files[index][''size''] > $my_size * mb) {
uploadErrors.push(''Filesize is too big'');
};
};
}; // << all_formats
// when errors
if(uploadErrors.length > 0) {
// alert(uploadErrors.join("/n"));
// mark index of error file
error_uploads_indexes.push(index);
// alert error
alert(uploadErrors.join("/n"));
};
}); // << each
// remove indexes (files) with error
data.files = $.grep( data.files, function( n, i ) {
return $.inArray(i, error_uploads_indexes) ==-1;
});
// if are files to upload
if(data.files.length){
// upload by ajax
var jqXHR = data.submit().done(function (result, textStatus, jqXHR) {
//...
alert(''done!'') ;
// ...
});
} //
}, // << add
progressall: function (e, data) {
var progress = parseInt(data.loaded / data.total * 100, 10);
$progressbar.css(
''width'',
progress + ''%''
);
}
}); // << file_upload
//
}); // << each input file
Esto funcionó para mí en Chrome, la versión jquery.fileupload.js es 5.42.3
add: function(e, data) {
var uploadErrors = [];
var ext = data.originalFiles[0].name.split(''.'').pop().toLowerCase();
if($.inArray(ext, [''odt'',''docx'']) == -1) {
uploadErrors.push(''Not an accepted file type'');
}
if(data.originalFiles[0].size > (2*1024*1024)) {//2 MB
uploadErrors.push(''Filesize is too big'');
}
if(uploadErrors.length > 0) {
alert(uploadErrors.join("/n"));
} else {
data.submit();
}
},
Esto funciona para mí en Firefox
$(''#fileupload'').fileupload({
dataType: ''json'',
//acceptFileTypes: /(/.|//)(xml|pdf)$/i,
//maxFileSize: 15000000,
add: function (e, data) {
var uploadErrors = [];
var acceptFileTypes = ///(pdf|xml)$/i;
if(data.originalFiles[0][''type''].length && !acceptFileTypes.test(data.originalFiles[0][''type''])) {
uploadErrors.push(''File type not accepted'');
}
console.log(data.originalFiles[0][''size'']) ;
if (data.originalFiles[0][''size''] > 5000000) {
uploadErrors.push(''Filesize too big'');
}
if(uploadErrors.length > 0) {
alert(uploadErrors.join("/n"));
} else {
data.context = $(''<p/>'').text(''Uploading...'').appendTo(document.body);
data.submit();
}
},
done: function (e, data) {
data.context.text(''Success!.'');
}
});
Si tiene todo el plugin JS importado y en el orden correcto, pero todavía tiene problemas, parece que al especificar su propio manejador de "agregar" se borra el del complemento * -validate.js, que normalmente se activaría fuera de toda la validación llamando a data.process (). Entonces, para solucionarlo solo haz algo como esto en tu controlador de eventos "add":
$(''#whatever'').fileupload({
...
add: function(e, data) {
var $this = $(this);
data.process(function() {
return $this.fileupload(''process'', data);
}).done(function(){
//do success stuff
data.submit(); <-- fire off the upload to the server
}).fail(function() {
alert(data.files[0].error);
});
}
...
});
Solo un ejemplo de controlador de eventos para Agregar evento. Supone que la opción singleFileUploads está habilitada (que es la predeterminada). Lea más documentación de jQuery File Upload sobre cómo enlazar con el evento add / fileuploadadd. Dentro del ciclo puede usar ambos archivos este o archivo . Un ejemplo de cómo obtener propiedades de tamaño: this [''size''] o file.size .
/**
* Handles Add event
*/
base.eventAdd = function(e, data) {
var errs = [];
var acceptFileTypes = /(/.|//)(gif|jpe?g|png)$/i;
var maxFileSize = 5000000;
// Validate file
$.each(data.files, function(index, file) {
if (file.type.length && !acceptFileTypes.test(file.type)) {
errs.push(''Selected file "'' + file.name + ''" is not alloawed. Invalid file type.'');
}
if (this[''size''] > maxFileSize) {
errs.push(''Selected file "'' + file.name + ''" is too big, '' + parseInt(file.size / 1024 / 1024) + ''M.. File should be smaller than '' + parseInt(maxFileSize / 1024 / 1024) + ''M.'');
}
});
// Output errors or submit data
if (errs.length > 0) {
alert(''An error occured. '' + errs.join(" "));
} else {
data.submit();
}
};
También podría usar una función adicional como:
function checkFileType(filename, typeRegEx) {
if (filename.length < 4 || typeRegEx.length < 1) return false;
var filenameParts = filename.split(''.'');
if (filenameParts.length < 2) return false;
var fileExtension = filenameParts[filenameParts.length - 1];
return typeRegEx.test(''.'' + fileExtension);
}
Tuve el mismo problema, y el chico de blueimp dice " maxFileSize y acceptFileTypes solo son compatibles con la versión de UI " y ha proporcionado un enlace (roto) para incorporar los métodos _validate y _hasError.
Entonces, sin saber cómo incorporar esos métodos sin estropear el script, escribí esta pequeña función. Parece que funciona para mí.
Solo agregue esto
add: function(e, data) {
var uploadErrors = [];
var acceptFileTypes = /^image//(gif|jpe?g|png)$/i;
if(data.originalFiles[0][''type''].length && !acceptFileTypes.test(data.originalFiles[0][''type''])) {
uploadErrors.push(''Not an accepted file type'');
}
if(data.originalFiles[0][''size''].length && data.originalFiles[0][''size''] > 5000000) {
uploadErrors.push(''Filesize is too big'');
}
if(uploadErrors.length > 0) {
alert(uploadErrors.join("/n"));
} else {
data.submit();
}
},
al inicio de las opciones de .fileupload como se muestra en su código aquí
$(document).ready(function () {
''use strict'';
$(''#fileupload'').fileupload({
add: function(e, data) {
var uploadErrors = [];
var acceptFileTypes = /^image//(gif|jpe?g|png)$/i;
if(data.originalFiles[0][''type''].length && !acceptFileTypes.test(data.originalFiles[0][''type''])) {
uploadErrors.push(''Not an accepted file type'');
}
if(data.originalFiles[0][''size''].length && data.originalFiles[0][''size''] > 5000000) {
uploadErrors.push(''Filesize is too big'');
}
if(uploadErrors.length > 0) {
alert(uploadErrors.join("/n"));
} else {
data.submit();
}
},
dataType: ''json'',
autoUpload: false,
// acceptFileTypes: /(/.|//)(gif|jpe?g|png)$/i,
// maxFileSize: 5000000,
done: function (e, data) {
$.each(data.result.files, function (index, file) {
$(''<p style="color: green;">'' + file.name + ''<i class="elusive-ok" style="padding-left:10px;"/> - Type: '' + file.type + '' - Size: '' + file.size + '' byte</p>'')
.appendTo(''#div_files'');
});
},
fail: function (e, data) {
$.each(data.messages, function (index, error) {
$(''<p style="color: red;">Upload file error: '' + error + ''<i class="elusive-remove" style="padding-left:10px;"/></p>'')
.appendTo(''#div_files'');
});
},
progressall: function (e, data) {
var progress = parseInt(data.loaded / data.total * 100, 10);
$(''#progress .bar'').css(''width'', progress + ''%'');
}
});
});
Notarás que también agregué una función de tamaño de archivo porque eso solo funcionará en la versión de la interfaz de usuario.
Se actualizó para resolver el problema sugerido por @lopsided: Se data.originalFiles[0][''type''].length
data.originalFiles[0][''size''].length
y data.originalFiles[0][''size''].length
en las consultas para asegurarse de que existen y no están vacíos. primero antes de probar los errores. Si no existen, no se mostrará ningún error y solo se basará en las pruebas de error del lado del servidor.
abra el archivo llamado "jquery.fileupload-ui.js", verá el código así:
$.widget(''blueimp.fileupload'', $.blueimp.fileupload, {
options: {
// By default, files added to the widget are uploaded as soon
// as the user clicks on the start buttons. To enable automatic
// uploads, set the following option to true:
acceptFileTypes: /(/.|//)(gif|jpe?g|png)$/i,
autoUpload: false,
// The ID of the upload template:
uploadTemplateId: ''template-upload'',
// The ID of the download template:
downloadTemplateId: ''template-download'',
。。。。
solo agregue un código de línea --- el nuevo atributo "acceptFileTypes", como este:
options: {
// By default, files added to the widget are uploaded as soon
// as the user clicks on the start buttons. To enable automatic
// uploads, set the following option to true:
**acceptFileTypes: /(/.|//)(gif|jpe?g|png)$/i,**
autoUpload: false,
// The ID of the upload template:
uploadTemplateId: ''template-upload'',
// The ID of the download template:
downloadTemplateId: ''template-d
¡Ahora verás que todo está bien! ~ solo llevas el atributo a un lugar equivocado.
.fileupload({
add: function (e, data) {
var attachmentValue = 3 * 1000 * 1024;
var totalNoOfFiles = data.originalFiles.length;
for (i = 0; i < data.originalFiles.length; i++) {
if (data.originalFiles[i][''size''] > attachmentValue) {
$attachmentsList.find(''.uploading'').remove();
$attachmentMessage.append("<li>" + ''Uploaded bytes exceeded the file size'' + "</li>");
$attachmentMessage.show().fadeOut(10000, function () {
$attachmentMessage.html('''');
});
data.originalFiles.splice(i, 1);
}
}
if (data.files[0]) {
$attachmentsList
.prepend(''<li class="uploading" class="clearfix loading-content">'' + data.files[0].name + ''</li>'');
}
data.submit();
}
- También puede usar la extensión de archivo para verificar el tipo de archivo.
La forma más simple sería hacer algo como se indica a continuación dentro de agregar:
add : function (e,data){ var extension = data.originalFiles[0].name.substr( (data.originalFiles[0].name.lastIndexOf(''.'') +1) ); switch(extension){ case ''csv'': case ''xls'': case ''xlsx'': data.url = <Your URL>; data.submit(); break; default: alert("File type not accepted"); break; } }