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

Asked

Viewed 1,650 times

9

My question is the following: I can pass to the controller OR the file OR form. I wanted to know if there is any type (like Formcollection, but this apparently only receives the form itself, the files posted together not) that receives both the form and the file in a POST only. I’ve researched information about it but it is always sent the file alone, and I wanted to send 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 {});
}

3 answers

4

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

For demonstration purposes, I 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:

inserir a descrição da imagem aqui

I entered the payload via Wireshark. This is the request sent to the server:

POST /script/OpCenter/samplewebpart.aspx HTTP/1.1
Host: [SERVER].[DOMAIN]
Connection: keep-alive
Content-Length: 12373
Cache-Control: max-age=0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Origin: http://[SERVER].[DOMAIN]
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.125 Safari/537.36
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryCYhgqEfRdnZkrdRf
Referer: http://[SERVER].[DOMAIN]/script/OpCenter/samplewebpart.aspx
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8,pt;q=0.6

------WebKitFormBoundaryCYhgqEfRdnZkrdRf
Content-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 the hidden state control fields of ASP.NET, __VIEWSTATE and __EVENTVALIDATION, are present in the content Multipart.)

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

1) Prepare the data to be sent by packaging it in an instance of the Formdata class

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

(At this time, include all the data you need, including those on the form, via data.append.)

2) Perform your Ajax call by passing the Formdata instance as 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 (accepted answer.)

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

(The references are in English.)

  • 1

    And the treatment on the server as it would be?

0

This is a question I had a long time ago and researching I arrived at 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 a same request to the server.

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

But although there are already servers implementing these new HTTP standards. At ensure that this type of support will be maintained in the final version.

  • HTTP 1.1 supports Content-Type: Multipart/*, which is theoretically what it needs.

  • @Onosendai, Oohh, was hoping to be denied, but Content-Type multipart/* allows you to send an image and form in the same request? And the server will know how to process this easily. Or will you have to read the entire request manually? I will wait for your reply and then remove my reply (if proven incorrect).

  • Updated response!

0

Yes there is, for demonstration I made some changes to your equal form in the illustrative figures 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:

inserir a descrição da imagem aqui

inserir a descrição da imagem aqui


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:

inserir a descrição da imagem aqui

Browser other questions tagged

You are not signed in. Login or sign up in order to post.