How to make a POST that passes beyond the form, a file?

9

My question is this: I can move to the controller OR the file OR the form. I was wondering if there is any type (same FormCollection, however this apparently only gets the form itself, the files posted together does not) that it receives both the form and the file in a POST only. I have already researched information but the file is always sent by itself, and I wanted to send it along with the form.

HTML

<input type="text" name="nome"/>
<input type="text" name="Sobrenome"/>
<input type="file" id="FileUpload1" /> &nbsp;
<button id="btnEnviarArquivo" style="margin left:-6px;">Enviar Arquivo</button>
<button type="button" id="Enviar">Enviar</button>

Javascript

$.ajax({
    url: "/Home/Cadastro",
    type: "POST",
    data: data,
    success: function (data) {

    }

});

Controller

public JsonResult Cadastro(FormCollection form)
{
     return Json(new {});
}
    
asked by anonymous 24.07.2014 / 18:53

3 answers

4

You will need to implement requests of type Multipart , part of the HTTP 1.1 specification.

For demonstration purposes, I have created the following webform , containing text fields and a fileupload:

<%@ Page Language="C#" (...)%>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
        <div>
            <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
            <asp:FileUpload ID="FileUpload1" runat="server" />
            <asp:Button ID="Button1" runat="server" Text="Button" />
        </div>
    </form>
</body>
</html>

Whose appearance, when viewed in Chrome, is as follows:

I'veinterceptedthepayloadviaWireshark.Thisistherequestsenttotheserver:

POST/script/OpCenter/samplewebpart.aspxHTTP/1.1Host:[SERVER].[DOMAIN]Connection:keep-aliveContent-Length:12373Cache-Control:max-age=0Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8Origin:http://[SERVER].[DOMAIN]User-Agent:Mozilla/5.0(WindowsNT6.1;WOW64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/36.0.1985.125Safari/537.36Content-Type:multipart/form-data;boundary=----WebKitFormBoundaryCYhgqEfRdnZkrdRfReferer:http://[SERVER].[DOMAIN]/script/OpCenter/samplewebpart.aspxAccept-Encoding:gzip,deflate,sdchAccept-Language:en-US,en;q=0.8,pt;q=0.6------WebKitFormBoundaryCYhgqEfRdnZkrdRfContent-Disposition:form-data;name="__VIEWSTATE"
/wEPDwULLTEwNjc5MDgzOTQPZBYCAgMPFgIeB2VuY3R5cGUFE211bHRpcGFydC9mb3JtLWRhdGFkZOW8eX8I0G+ceXPjDwfXA1MRJuxEFHvp1y5twOS3H9uw

------WebKitFormBoundaryCYhgqEfRdnZkrdRf
Content-Disposition: form-data; name="__EVENTVALIDATION"

/wEWAwLQ+p/sDwLs0bLrBgKM54rGBqByybWBtQAZmIHlcbrUlcixkQ/+JlgNypmZ4vFxAn6b
------WebKitFormBoundaryCYhgqEfRdnZkrdRf
Content-Disposition: form-data; name="TextBox1"

teste
------WebKitFormBoundaryCYhgqEfRdnZkrdRf
Content-Disposition: form-data; name="FileUpload1"; filename="Alert.png"
Content-Type: image/png

.PNG
....IHDR.............\r.f....gAMA....7.......tEXtSoftware.Adobe ImageReadyq.e<..,.IDATx..}y..wu......5..4:,....,..O..l.M.......q..5.\.%......;$..
(mais ou menos 12Kb depois...)
.f....'0...^..'0.0..&......'0.........'.'0.L.......'0.0..&......'0....F....0.p9.Xd..F....IEND.B'.

------WebKitFormBoundaryCYhgqEfRdnZkrdRf
Content-Disposition: form-data; name="Button1"

Button
------WebKitFormBoundaryCYhgqEfRdnZkrdRf--

(Note that even hidden ASP.NET state control fields, __VIEWSTATE and __EVENTVALIDATION , are present in multipart content.)

That said, let's go to the client side solution using jQuery and Ajax:

1) Prepare the data to be sent by packaging them into an instance of the FormData class

var data = new FormData();
jQuery.each($('#file')[0].files, function(i, file) {
    data.append('file-'+i, file);
});

(Include, at this time, all the data you need, including those in the form, via data.append .)

2) Perform your Ajax call by passing the instance of FormData as a parameter:

$.ajax({
    url: 'paginadestino.aspx',
    data: data,
    cache: false,
    contentType: false,
    processData: false,
    type: 'POST',
    success: function(data){
        alert(data);
    }
});

References:

This is a way to implement Client side Multipart in an Ajax call (answer accepted.)

This post has an example of how to treat multipart server side (in C #).

(References are in English.)

    
24.07.2014 / 19:51
0

This is a question that I had a long time ago and researching I got the following answers / conclusions:

As far as my knowledge goes, currently the answer is no, it is not possible to send data from a form and a file in the same request to the server.

I am currently saying why we are currently using HTTP 1.1 (which is from 1995/1996) , which does not support this type of request. But SPDY (by Google) and HTTP 2.0 (which is the new HTTP standard in development, and is based on SPDY), are intended to address these limitations of HTTP 1.1.

  

But although there are already servers implementing these new HTTP standards. In guarantee that this type of support will be kept in the final version.

    
24.07.2014 / 19:24
0

Yes, there are some changes to your form, as shown in the illustration below, and the examples are for WebForms and MVC ASP.NET .

1 - MVC

View:

@{ Layout = null; }
<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Upload</title>
    <script src="~/Scripts/jquery-2.1.1.js"></script>
</head>
<body>
    <form name="Form1" id="Form1">
        <label>Nome:</label>
        <input type="text" name="nome" id="nome" /><br />
        <label>Sobrenome:</label>
        <input type="text" name="sobrenome" id="sobrenome" /><br />
        <label>Arquivo:</label>
        <input type="file" id="fileupload" /><br />        
        <button type="button" id="Enviar">Enviar</button>
    </form>
    <script>
        $(function () {
            $("#Enviar").on("click", function () {
                var form = new FormData();
                $.each($("#Form1 #fileupload")[0].files, function(idx, file){
                    form.append("FileUpload", file);
                });
                form.append('Nome', $("#nome").val());
                form.append('SobreNome', $("#sobrenome").val());
                $.ajax({
                    url: '@Url.Action("Upload")',
                    data: form,
                    cache: false,
                    contentType: false,
                    processData: false,
                    type: 'POST',
                    success: function (data) {
                        alert(data);
                    }
                });
            });
        });
    </script>
</body>
</html>

Action Result:

public ActionResult Upload()
{
    return View();
}

[HttpPost]
public ActionResult Upload(String Nome, String SobreNome, HttpPostedFileBase FileUpload)
{
    return View();
}

Expected result:

2 - WebForms

ASPX

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Upload.aspx.cs" Inherits="WebApplicationForms.Upload" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Upload</title>
    <script src="Scripts/jquery-1.10.2.js"></script>
</head>
<body>
    <form id="Form1" runat="server">
        <label>Nome:</label>
        <input type="text" name="nome" id="nome" /><br />
        <label>Sobrenome:</label>
        <input type="text" name="sobrenome" id="sobrenome" /><br />
        <label>Arquivo:</label>
        <input type="file" id="fileupload" /><br />
        <button type="button" id="Enviar">Enviar</button>
        <script>
            $(function () {
                $("#Enviar").on("click", function () {
                    var form = new FormData();
                    $.each($("#Form1 #fileupload")[0].files, function (idx, file) {
                        form.append("FileUpload", file);
                    });
                    form.append('Nome', $("#nome").val());
                    form.append('SobreNome', $("#sobrenome").val());
                    $.ajax({
                        url: 'Upload.ashx',
                        data: form,
                        cache: false,
                        contentType: false,
                        processData: false,
                        type: 'POST',
                        success: function (data) {
                            alert(data.Ok);
                        }
                    });
                });
            });
        </script>
    </form>
</body>
</html>

File Upload.ashx (handler):

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace WebApplicationForms
{    
    public class Upload1 : IHttpHandler
    {

        public void ProcessRequest(HttpContext context)
        {
            String Nome = context.Request.Form["Nome"].ToString();
            String SobreNome = context.Request.Form["SobreNome"].ToString();
            HttpPostedFile FileUpload = context.Request.Files["FileUpload"];

            context.Response.Clear();
            context.Response.ContentType = "application/json";
            context.Response.Flush();
            context.Response.Write(JsonConvert.SerializeObject(new {Ok = true}));
        }

        public bool IsReusable
        {
            get
            {
                return false;
            }
        }
    }
}

Expected result:

    
26.08.2014 / 19:06