Submit Additional Form Data without setting formDa

2019-07-04 01:02发布

I am following How-to-submit-additional-form-data and have a working fileupload that is submitting the additional form data, ie. the additional textarea input field, description[], with chunking and multiple file support without setting formData:{ } on .fileupload(). My problem is that I am only able to submit the field as an array, description[], and I am unable to come up with some logic to associate the appropriate description[i] with the appropriate file. I am using asp.net mvc which should not matter in this case.

The View:

<script type="text/javascript">
    $(document).ready(function () {
        $('#btnContinue').prop('disabled', true);
        $('#fileupload').fileupload({
            url: '@Url.Action("UploadChunk", "Upload")',
            maxChunkSize: 1048576,
        }).addClass('fileupload-processing')
        .bind('fileuploadalways', function (e, data) {
            if ($('#fileIds').val().indexOf(';' + data.result.id + ';') == -1) {
                var pre = $('#fileIds').val() == "" ?  ';' : '';
                var append = $('#fileIds').val() + pre + data.result.id + ';';
                $('#fileIds').val(append);
            }
        })
        .bind('fileuploaddone', function (e, data) {
            $('#btnContinue').prop('disabled', false);
        });

        $.ajax({
            url: $('#fileupload').fileupload('option', 'url'),
            dataType: 'json',
            context: $('#fileupload')[0]
        }).always(function () {
            $(this).removeClass('fileupload-processing');
        });
    });
</script>
@using (Html.BeginForm("FileSet", "Upload", FormMethod.Post, new { id = "fileupload" } ))
{
    @Html.AntiForgeryToken()
    @Html.Hidden("fileIds", "", new { @id = "fileIds" })

    <div class="form-horizontal">
        <hr />
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })

        <div class="row fileupload-buttonbar">
            <div class="col-lg-7">
                <!-- The fileinput-button span is used to style the file input field as button -->
                <span class="btn btn-success fileinput-button">
                    <i class="glyphicon glyphicon-plus"></i>
                    <span>Add files...</span>
                    <input type="file" name="files[]" multiple>
                </span>
                <button type="submit" class="btn btn-primary start" id="btnStartUpload">
                    <i class="glyphicon glyphicon-upload"></i>
                    <span>Start upload</span>
                </button>
                <button type="reset" class="btn btn-warning cancel" id="btnCancelUpload">
                    <i class="glyphicon glyphicon-ban-circle"></i>
                    <span>Cancel upload</span>
                </button>
                <button type="button" class="btn btn-danger delete" id="btnDeleteUpload">
                    <i class="glyphicon glyphicon-trash"></i>
                    <span>Delete</span>
                </button>
                <input style="visibility: hidden" type="checkbox" class="toggle">
                <!-- The global file processing state -->
                <span class="fileupload-process"></span>
            </div>
            <!-- The global progress state -->
            <div class="col-lg-5 fileupload-progress fade">
                <!-- The global progress bar -->
                <div class="progress progress-striped active" role="progressbar" aria-valuemin="0" aria-valuemax="100">
                    <div class="progress-bar progress-bar-success" style="width:0%;"></div>
                </div>
                <!-- The extended global progress state -->
                <div class="progress-extended">&nbsp;</div>
            </div>
        </div>
        <table role="presentation" class="table table-striped"><tbody class="files"></tbody></table>     

        <div class="row">
            <div class="col-md-10">
                <button type="submit" id="btnContinue" class="btn btn-primary">Continue</button>
            </div>
        </div>
    </div>
}

<!-- The template to display files available for upload -->
<script id="template-upload" type="text/x-tmpl">
{% for (var i=0, file; file=o.files[i]; i++) { %}
<tr class="template-upload fade">
    <td>
        <span class="preview"></span>
    </td>
    <td>
        <p class="name">{%=file.name%}</p>
        <strong class="error text-danger"></strong>
    </td>
    <td>
        <input type="hidden" name="locator[]" value="{%=file.name%}" />
        <textarea name="description[]" placeholder="Enter description" class="form-control" rows="3"></textarea>
        <strong class="error text-danger"></strong>
    </td>
    <td>
        <p class="size">Processing...</p>
        <div class="progress progress-striped active" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0"><div class="progress-bar progress-bar-success" style="width:0%;"></div></div>
    </td>
    <td>
        {% if (!i && !o.options.autoUpload) { %}
        <button class="btn btn-primary start" disabled>
            <i class="glyphicon glyphicon-upload"></i>
            <span>Start</span>
        </button>
        {% } %}
        {% if (!i) { %}
        <button class="btn btn-warning cancel">
            <i class="glyphicon glyphicon-ban-circle"></i>
            <span>Cancel</span>
        </button>
        {% } %}
    </td>
</tr>
{% } %}
</script>
<!-- The template to display files available for download -->
<script id="template-download" type="text/x-tmpl">
{% for (var i=0, file; file=o.files[i]; i++) { %}
<tr class="template-download fade">
    <td>
        <span class="preview">
            {% if (file.thumbnailUrl) { %}
            <a href="{%=file.url%}" title="{%=file.name%}" download="{%=file.name%}" data-gallery><img src="{%=file.thumbnailUrl%}"></a>
            {% } %}
        </span>
    </td>
    <td>
        <p class="name">
            {% if (file.url) { %}
            <a href="{%=file.url%}" title="{%=file.name%}" download="{%=file.name%}" {%=file.thumbnailUrl?'data-gallery':''%}>{%=file.name%}</a>
            {% } else { %}
            <span>{%=file.name%}</span>
            {% } %}
        </p>
        {% if (file.error) { %}
        <div><span class="label label-danger">Error</span> {%=file.error%}</div>
        {% } %}
    </td>
    <td>
        <span class="size">{%=o.formatFileSize(file.size)%}</span>
    </td>
    <td>
        {% if (file.deleteUrl) { %}
        <button class="btn btn-danger delete" data-type="{%=file.deleteType%}" data-url="{%=file.deleteUrl%}" {% if (file.deletewithcredentials) { %} data-xhr-fields='{"withCredentials":true}' {% } %}>
            <i class="glyphicon glyphicon-trash"></i>
            <span>Delete</span>
        </button>
        <input type="checkbox" name="delete" value="1" class="toggle">
        {% } else { %}
        <button class="btn btn-warning cancel">
            <i class="glyphicon glyphicon-ban-circle"></i>
            <span>Cancel</span>
        </button>
        {% } %}
    </td>
</tr>
{% } %}

The Controller:

[HttpPost]
public ContentResult UploadChunk(string[] description)
{
    ParseRequestHeaderRanges(this.Request);
    var r = new List<UploadFilesResult>();
    var i = 0;

    foreach (string file in Request.Files)
    {
        HttpPostedFileBase hpf = Request.Files[file] as HttpPostedFileBase;
        if (hpf.ContentLength == 0)
            continue;

        var uploader = System.Security.Principal.WindowsIdentity.GetCurrent().Name;
        var result = DataTranslator.UploadChunk(hpf.InputStream, hpf.FileName, description[i], hpf.ContentType,
            hpf.ContentLength, (int)hpf.InputStream.Length, this.TotalBytes, uploader);
        r.Add(result);
        i++;
    }

    return Content("{\"id\":\"" + r[0].Id + "\",\"name\":\"" + r[0].Name + "\",\"type\":\"" + r[0].Type + "\",\"size\":\"" + string.Format("{0} bytes", r[0].Length) + "\"}", "application/json");
}

1条回答
贪生不怕死
2楼-- · 2019-07-04 01:38

Rather than have it be an array make it a hash? Say using the filename? That way you don't have to rely on things being in the right order.

<textarea name="description[{%=file.name%}]" placeholder="Enter description" class="form-control" rows="3"></textarea>

And in the controller:

var result = DataTranslator.UploadChunk(
  hpf.InputStream, 
  hpf.FileName, 
  description[hpf.FileName],
  hpf.ContentType, 
  hpf.ContentLength, 
  (int)hpf.InputStream.Length, 
  this.TotalBytes, 
  uploader
);
查看更多
登录 后发表回答