none
Subir imagen y poder previsualizarla antes de guardarla RRS feed

  • Debate general

  • Hola! Les cuento que estoy desarrollando una aplicación de prueba, donde una de las funciones es administrar productos. Cada producto tiene una descripción, una imagen y algunos otros atributos. Hasta ahora he podido realizar cargar los productos junto a su imagen, mostrarlos y cambiar la imagen.

    Lo que quisiera saber es cómo podría lograr que cuando el usuario seleccione la imagen que desea para un producto la misma se previsualice (en lugar de la imagen actual del producto).

    No tengo mucha práctica con ajax, pero ¿habría alguna forma de pasarle la imagen y que refresque solo el tag <img/>?

    Desde ya gracias por su tiempo :)

    Saludos!

    sábado, 12 de marzo de 2011 16:46

Todas las respuestas

  • Hola de nuevo, les cuento que seguí intentando y adapté el ejemplo que aparece en http://weblogs.asp.net/imranbaloch/archive/2010/04/03/image-preview-in-asp-net-mvc.aspx sin embargo, aparentemente no está cargando la imagen, porque Session["ContentStream"] siempre es igual a null. ¿Alguna idea de a qué pueda deberse?

    El código de mi Vista es:

     <script src="@Url.Content("~/Scripts/jquery.form.js")" type="text/javascript"></script>    
    
      <script type="text/javascript">
        function ChangeImage(fileId, imageId) {
          $("#form1").ajaxSubmit({ success: function (responseText) {
            var d = new Date();
            $(imageId)[0].src = "/GestionProductos/ImageLoad?a=" + d.getTime();
          }
          });
        }
    
    </script>
        <div class="editor-label">
          <strong>@Html.Label("Descripción del producto: ")</strong>
        </div>
        <div class="editor-field">
          @Html.EditorFor(model => model.DescripcionProducto)
          @Html.ValidationMessageFor(model => model.DescripcionProducto)
        </div>
    
        <div>
        <p>
            <img alt="" src='@Url.Action("Imagen", "GestionProductos", new { id = Model.ProductoId })' id="imgThumbnail" height="150" width="250" />
        </p>
        <p>
          <input type="file" name="imageLoad1" id="imageLoad1" onchange="ChangeImage(this,'#imgThumbnail')" />
        </p>
        </div> 
            
        <div class="editor-label">
          <strong>@Html.Label("Observaciones: ")</strong>
        </div>
        <div class="editor-field">
          @Html.EditorFor(model => model.ObservacionesProducto)
          @Html.ValidationMessageFor(model => model.ObservacionesProducto)
        </div>
    
    

    y el del Controlador

    public class GestionProductosController : Controller
      {
    
      public ActionResult ImageLoad(int? id) 
      {     
        byte[] b = (byte[])Session["ContentStream"];
        int length = (int)Session["ContentLength"]; 
        string type = (string)Session["ContentType"]; 
        
        Response.Buffer = true; Response.Charset = ""; 
        Response.Cache.SetCacheability(HttpCacheability.NoCache); 
        Response.ContentType = type; Response.BinaryWrite(b); 
        Response.Flush(); 
        
        Session["ContentLength"] = null; 
        Session["ContentType"] = null; 
        Session["ContentStream"] = null; 
        
        Response.End(); 
        return Content(""); 
      }
    
    
    
    // más código
    //...
    //...
    //...
    //...
    
    }
    
    
    lunes, 14 de marzo de 2011 21:10
  • Laura,

    Donde estás enviando el <form>? No veo el tag <form> en tu vista...

    Si lo tienes: eso está usando la Session de ASP.NET. Asegúrate que la tienes habilitada en el web.config.

    Saludos!


    Eduard Tomàs Blog: http://geeks.ms/blogs/etomas -- Twitter: eiximenis
    martes, 15 de marzo de 2011 11:33
  • Las tag de <form> las declaro en otra vista, desde dónde llamo a la vista que está en el post anterior. La otra vista es la siguiente:
    @model MvcPrueba.Models.Producto @{ ViewBag.Title = "Modificar Producto"; } 
    Modificar Producto
    <form id="form1" method="post" action="/GestionProductos/Edit" enctype = "multipart/form-data"> 
    
    @Html.ValidationSummary(true) <fieldset> <legend>@Model.DescripcionProducto</legend> 
    @Html.EditorForModel()//Con esta línea llamo a la vista anterior 
    
    <input type="submit" value="Guardar" /> </fieldset> 
    </form> 
    
    @Html.ActionLink("Volver a la lista", "Index") 
    y dentro del web.config tengo:
    <system.web> 
    <roleManager enabled="true" /> 
    <sessionState mode="InProc" 
        timeout="20"/> 
    Sin embargo Session["ContentStream"] siempre es igual a null... ¿Estoy haciendo algo mal?
    martes, 15 de marzo de 2011 16:20
  • Laura,

    falta ver que haces dentro de la acción Edit del controlador GestionProductos, pues esta es quien recibe los datos y debería poner algo en la sesión, que accedes luego en la acción ImageLoad!

    Saludos!


    Eduard Tomàs Blog: http://geeks.ms/blogs/etomas -- Twitter: eiximenis
    miércoles, 16 de marzo de 2011 8:16
  • De vuelta por acá, después de guerrear mucho con este tema. La propuesta que publiqué más arriba no me dió resultado, ya que necesitaba subir la imagen sin enviar todo el formulario.

    Sin embargo encontré otra aproximación (también empleando jquery) que si me funcionó. La expongo a continuación por si a alguno le sirve.

    En mi controlador agregué los métodos:

      [AcceptVerbs(HttpVerbs.Post)]
      public ActionResult AjaxSubmit(int? id)
      {
        Session["ContentLength"] = Request.Files[0].ContentLength;
        Session["ContentType"] = Request.Files[0].ContentType;
        byte[] b = new byte[Request.Files[0].ContentLength];
        Request.Files[0].InputStream.Read(b, 0, Request.Files[0].ContentLength);
        Session["ContentStream"] = b;
        return Content(Request.Files[0].ContentType + ";" + Request.Files[0].ContentLength);
      }
    
    
      public ActionResult ImageLoad(int? id)
      {
        byte[] b = (byte[])Session["ContentStream"];
        int length = (int)Session["ContentLength"];
        string type = (string)Session["ContentType"];
        Response.Buffer = true;
        Response.Charset = "";
        Response.Cache.SetCacheability(HttpCacheability.NoCache);
        Response.ContentType = type;
        Response.BinaryWrite(b);
        Response.Flush();
        Response.End();
        Session["ContentLength"] = null;
        Session["ContentType"] = null;
        Session["ContentStream"] = null;
        return Content("");
      }
    
    

     y mi método edit lo armé de la siguiente forma:

    [HttpPost]
    public ActionResult Edit(int id, FormCollection collection, HttpPostedFileBase imageLoad2)
        {             
          var producto = db.Productos.Find(id);
    
          if ((imageLoad2 != null) && (imageLoad2.ContentLength > 0))
          {
            byte[] imgBinaryData = new byte[imageLoad2.ContentLength]; 
            int readresult = imageLoad2.InputStream.Read(imgBinaryData, 0, imageLoad2.ContentLength);
            producto.Imagen = imgBinaryData;
          }
    
          if (TryUpdateModel(producto))
          {
            db.SaveChanges();
            return RedirectToAction("Index");
          }
          else
          {
            ViewBag.TiposDeProductos = db.TiposDeProductos.OrderBy(t => t.DescripcionTipoDeProducto);
    
            return View(producto);
          }
    

    La vista se mantuvo similar, pero cambié el script de la siguiente forma:

    <script type="text/javascript">
      function ChangeImage(fileId, imageId) {
        var myform = document.createElement("form");
        myform.style.display = "none";
        myform.action = "/GestionProductos/AjaxSubmit";
        myform.enctype = "multipart/form-data";
        myform.method = "post";
        var imageLoad;
        var imageLoadParent;
        var is_chrome = /chrome/.test(navigator.userAgent.toLowerCase());
        if (is_chrome && document.getElementById(fileId).value == '')
          return; //Chrome bug onchange cancel
        if (document.all || is_chrome) {//IE
          imageLoad = document.getElementById(fileId);
          imageLoadParent = document.getElementById(fileId).parentNode;
          myform.appendChild(imageLoad);
          document.body.appendChild(myform);
        }
        else {//FF
          imageLoad = document.getElementById(fileId).cloneNode(true);
          myform.appendChild(imageLoad);
          document.body.appendChild(myform);
        }
        $(myform).ajaxSubmit({ success:
        function (responseText) {
          var d = new Date();
          $(imageId)[0].src = "/GestionProductos/ImageLoad?a=" + d.getMilliseconds();
          if (document.all || is_chrome)//IE
            imageLoadParent.appendChild(myform.firstChild);
          else//FF           
            document.body.removeChild(myform);
        }
        });
      }
    </script>
    
    
    //
    //más código
    //
    
    
        <div>
          <p>
            <img alt="Preview" src='@Url.Action("Imagen", "GestionProductos", new { id = Model.ProductoId })' id="imgThumbnail2" height="100px" width="100px" /> 
          </p>
          <p>
            <input type="file" name="imageLoad2" id="imageLoad2" onchange="ChangeImage('imageLoad2','#imgThumbnail2')" />
          </p>
        </div>
    

    Seguramente hay muchas cosas que pueden pulirse, pero cumple con la posibilidad de previsualizar la imagen antes de enviar todo el formulario.

    Saludos!

    jueves, 31 de marzo de 2011 19:43