web-dev-qa-db-ja.com

ASP.NET Core MVC6のコントローラーへのファイルとモデルの投稿

ASP.NET RC1からASP.NET Core 1.0にプロジェクトを移行しています。

ユーザーが1つ以上のファイルをアップロードできるビューがあり、それをJquery Ajaxを使用して投稿します。また、同じ投稿内でいくつかの設定をシリアル化して投稿します。

以下はすべてRC1(およびpre-asp.netコア)で機能しました。

Js:

    $('#submit').click(function () {      
        var postData = $('#fields :input').serializeArray();
        var fileSelect = document.getElementById('file-select');
        var files = fileSelect.files;

        var data = new FormData();
        for (var i = 0; i < files.length; i++) {
            data.append('file' + i, files[i]);
        }
        $.each(postData, function (key, input) {
            data.append(input.name, input.value);
        });
        var url = '/ajax/uploadfile';
        $.ajax({
            url: url,
            type: "POST",
            contentType: false,
            processData: false,
            cache: false,
            data: data,
            success: function (result) {
                alert('success');                   
            },
            error: function () {
                alert('error'); 
            }
        });
    });

コントローラ:

  public IActionResult UploadFile(UploadFileModel model)
    {
        var result = new JsonResultData();
        try
        {
            if (Request.Form.Files.Count > 0)
            {
                IFormFile file = Request.Form.Files[0];
                //etc
             }
        }
     }

上記は機能しなくなり、ファイルはアップロードされず、モデルはバインドされません。問題の半分を修正できたので、次のコードでモデルをバインドできます。ただし、コントローラーはRequest.Files。 'headers'プロパティを追加し、serializeObject(カスタムメソッド)を使用しました。コントローラにFromBodyを追加しました。

Js:

 $('#submit').click(function () {      
        var postData = $('#fields :input').serializeArray();
        var fileSelect = document.getElementById('file-select');
        var files = fileSelect.files;

        var data = new FormData();
        for (var i = 0; i < files.length; i++) {
            data.append('file' + i, files[i]);
        }
        $.each(postData, function (key, input) {
            data.append(input.name, input.value);
        });
        var url = '/ajax/uploadfile';
        $.ajax({
            url: url,
            type: "POST",
            headers: {
                'Accept': 'application/json',
                'Content-Type': 'application/json'
            },
            processData: false,
            cache: false,
            data: serializeAndStingifyArray(data),
            success: function (result) {
                alert('success');                   
            },
            error: function () {
                alert('error'); 
            }
        });
    });

    function serializeAndStingifyArray(array) {
    var o = {};
    var a = array;
    $.each(a, function () {
        if (o[this.name] !== undefined) {
            if (!o[this.name].Push) {
                o[this.name] = [o[this.name]];
            }
            o[this.name].Push(this.value || '');
        } else {
            o[this.name] = this.value || '';
        }
    });
    return JSON.stringify(o);
};

コントローラ:

    [HttpPost]
    public IActionResult UploadFile([FromBody]UploadFileModel model)
    {
        var result = new JsonResultData();
        try
        {
            if (Request.Form.Files.Count > 0)
            {
                IFormFile file = Request.Form.Files[0];
                //etc
             }
         }
       }

html:

    <div id="file-list">
    <input type="file" name="file" class="file-select" accept="application/pdf,application">
    <input type="file" name="file" class="file-select"           accept="application/pdf,application" />
    </div>
11
user2713516

私はあなたのコードとほとんど同じであるいくつかのコードを含むこの記事から始めました ASP.NET Core 1.0でファイルをアップロード (Ajaxのケースを参照)。

1.0.0では問題なく動作したため、変更を実装しましたが、リクエストでファイルを送信できなかった(クライアント側の問題)ことがわかりました。

これは、ChromeでF12を使用して問題なく動作するときのペイロードの外観です(ファイルの内容がChromeによって非表示になっている理由がわかりません)。

payload

少しデバッグして、間違ったデータをdata.appendに渡しています

修正はこの行にあります

        $(".file-select").each(function () { data.append($(this).val(), $(this).get(0).files[0]); i++; })

完全なコード:

$(document).ready(function () {
    $("#submit").click(function (evt) {

        var data = new FormData();
        i = 0;

        $(".file-select").each(function () { data.append($(this).val(), $(this).get(0).files[0]); i++; })

        var postData = $('#fields :input');
        $.each(postData, function (key, input) {
            data.append(input.name, input.value);
        });

        $.ajax({
            type: "POST",
            url: "/ajax/uploadfile",     // <--- Double check this url.
            contentType: false,
            processData: false,
            data: data,
            success: function (message) {
                alert(message);
            },
            error: function () {
                alert("There was error uploading files!");
            }
        });
    });
});

[FromBody]またはserializeArray()を使用する必要はありません

    [HttpPost]
    public IActionResult UploadFilesAjax(MyViewModel xxx )
    {

これは念のため私のhtmlです:

<form method="post" enctype="multipart/form-data">

<div id="file-list">
    <input type="file" name="file" class="file-select" accept="application/pdf,application">
    <input type="file" name="file" class="file-select" accept="application/pdf,application" />
</div>
<div id="fields">
    <input type="text" name="Email" />
</div>

<input type="button"
        id="submit"
        value="Upload Selected Files" />
</form>
12