Subiendo múltiples archivos con .NET

Debido a algunos comentarios que recibí en la entrada "Enviar y/o subir multiples archivos adjuntos al estilo GMail" (varios se perdieron por problemas con el hosting) y algunos mails que he recibido, mostraré la forma de subir múltiples archivos con .NET.

Primero, veremos la forma de generar elementos HTML input de tipo file, para esto utilizo una versión mejorada del script que publiqué hace tiempo:

javascript:
// Tomado de http://www.quirksmode.org/blog/archives/2005/10/_and_the_winner_1.html
addEvent = function ( obj, type, fn ) {
        if (obj.addEventListener)
                obj.addEventListener( type, fn, false );
        else if (obj.attachEvent) {
                obj["e"+type+fn] = fn;
                obj[type+fn] = function() { obj["e"+type+fn]( window.event ); };
                obj.attachEvent( "on"+type, obj[type+fn] );
        }
}
bc_newElement = function (tag) {
   return document.createElement(tag);
}
bc_getElement = function (id) {
   return document.getElementById(id);
}

var field_count = 1;

bc_init = function(fileId, displayId) {
    try {
        field = bc_getElement(fileId);
        field.display=bc_getElement(displayId);

        if (!field || !field.type || field.type != 'file' || !field.display) return;

        addEvent(field, 'change', bc_addField);
    } catch ( ex ) { bc_handleError(ex); }
}

bc_load = function (fileId, displayId) {
    addEvent(window, 'load', new Function("bc_init('" + fileId + "', '" + displayId + "');"));
}
// Basado en http://the-stickman.com/web-development/javascript/updated-upload-multiple-files-with-a-single-file-element/
bc_addField = function() {
    try {
        new_field = bc_newElement('INPUT');
        new_field.type = 'file';
        new_field.id = new_field.name = this.id.replace(/-@bc-.*$/g, "") + '-@bc-' + field_count++;
        new_field.display = this.display;
        addEvent(new_field, 'change', bc_addField);

        this.parentNode.insertBefore(new_field, this);

        li = bc_newElement('LI');

        a = bc_newElement('A');
        a.href="#";
        a.appendChild(document.createTextNode('Quitar'));
        a.field_id = this.id;
        addEvent(a, 'click', bc_removeField);

        li.appendChild(a);
        li.appendChild(document.createTextNode( this.value.substring( this.value.search(/[^\/\]+$/) ) ));
        this.display.appendChild(li);

        this.style.position = 'absolute';
            this.style.left = '-1000px';
    } catch ( ex ) { bc_handleError(ex); }
}
bc_removeField = function (event) {
    try {
        (del = bc_getElement(this.field_id)).parentNode.removeChild(del);

        this.parentNode.parentNode.removeChild(this.parentNode);
        if (event && event.preventDefault)
            event.preventDefault();
        return false;
    } catch ( ex ) { bc_handleError(ex); }
}
bc_handleError = function (ex) { alert ( ex ); }

Para registrar el script mostrado arriba, se puede hacer tanto desde el HTML (ver ejemplo) así como también desde código del lado del servidor, para el último caso se puede hacer en el evento Page_Load o en el evento PreRender, de la siguiente manera:

csharp:
protected override void OnPreRender(EventArgs e)
{
        if(!Page.IsClientScriptBlockRegistered("bc_header_script"))
                Page.RegisterClientScriptBlock("bc_header_script", "<script type=\"text/javascript\" src=\"scripts/utils.js\"></script>");

        string init_script = string.Format("<script type=\"text/javascript\">bc_load('{0}', '{1}');</script>",
                inputField.ClientID, list_files.ClientID);
        Page.RegisterClientScriptBlock("bc_loader", init_script);
        base.OnPreRender(e);
}

A continuación, ponemos los elementos iniciales para que el script pueda hacer su trabajo:

html:
<div class="demo">
    <h2>Selecciona un archivo</h2>
    <p>
    <input id="inputField" type="file" runat="server" />
    <asp:Button ID="cmdUpload" runat="server" Text="Subir" />
    </p>
    <ul id="list_files" runat="server">
    </ul>
</div>

Finalmente, implementamos el método que se encargará de guardar los archivos subidos al servidor:

csharp:
private void cmdUpload_Click(object sender, System.EventArgs e)
{
        HttpFileCollection files = HttpContext.Current.Request.Files;
        for (int i = 0; i < files.Count; i++)
        {
                HttpPostedFile file = files[i];

                if (file.ContentLength == 0)
                        continue;
                try
                {
                        //upload.SaveAs(Path.Combine(@"C:\Uploads", file.FileName));
                        Response.Write(file.FileName);
                }
                catch
                {
                        // Manejar el error
                }
        }
}

Nota 1: El método presentado aquí para subir archivos se basa en la funcionalidad que trae ASP.NET, el cuál está limitado por la cantidad de bytes definido en el atributo maxRequestLength de la sección httpRuntime, así como también el tiempo máximo de ejecución del script. Este método normalmente falla cuando se suben archivos de tamaño considerable (la página no carga), felizmente este problema se puede solucionar usando módulos HTTP (ver NeatUpload).

Nota 2: Lamentablemente no puedo poner un demo para que vean funcionando el script, porque el servidor de hosting no soporta .NET

Archivos Relacionados

11 Replies to “Subiendo múltiples archivos con .NET”

  1. Pingback: meneame.net
  2. a la hora de descomentar //upload.SaveAs(Path.Combine(@"C:\Uploads", file.FileName));
    sale un errror.
    Para empezar hay que importar el system.io
    Imports System.io
    y luego el upload.saveas me parece solo funciona con el framework 2.0
    o me equivoco?
    gracias

  3. Hola Ivan,

    En efecto se necesita importar System.IO porque se está usando la clase Path, en cuanto al método SaveAs, si funciona en el framework 1.1

    Saludos y gracias por la observación.

  4. Hola. Estaba checando tu codigo porque necesito hacer una carga de archivos al servidor, pero tengo el mismo problemade Ivan, a la hora de descomentar el upload.SaveAs... Te agradeceria si puedes comentar más al respecto... Gracias y un cordial saludo desde Chiapas

  5. oye gracias por el codigo, esta excelente, en cuanto al error que les sale hay que cambiar el upload por el file
    file.SaveAs(....

  6. Hola, estoy intentando ejecutar todo éste código pero me da error un error de javascript al cargar la página:

    Se esperaba ']' en la expresión regular.

    ¿alguien sabe a que puede ser debido?

    Muchas gracias.

  7. Tengo el mismo error que Xisco y me aparece :

    Se esperaba ']' en la expresión regular. pero todavia no se como solucionarlo. Podrian ayudarme.
    Gracias.

  8. hola tengo un problema se poco sobre php pero necesito un formulario como este que me permita cargar arhivos pero en lugar de guardarlos en el servidor no se si se pudan enviar a una direccion de correo si alguien puede decirme como o proporcionarme el codigo se lo agradeciar

Comments are closed.