简体   繁体   English

如何允许从表单中独立上传文件?

[英]How can I allow independent file uploads from within a form?

I'm building a support contact form where the user can upload files.我正在构建一个支持联系表单,用户可以在其中上传文件。 The file upload is managed using AJAX: the user can upload the files, then submit the form at their convenience.文件上传使用 AJAX 管理:用户可以上传文件,然后在方便时提交表单。 The current layout that works is, however, not aesthetic: the upload input is below the form submit button.但是,当前有效的布局并不美观:上传输入位于表单提交按钮下方。

I read about nested forms and the new form attribute and I thought this would do the trick:我阅读了有关嵌套表单和新form属性的信息,我认为这可以解决问题:

<form action="" method="post" enctype="multipart/form-data" id="main-form">
...
    <form action="/upload_file_ajax.php" method="post" id="file-upload-form">
    <div class="form-group row mb-3 mb-3">
        <label class="col-sm-3 col-lg-3 col-form-label" for="file"><?php echo $label['attach-file']; ?></label>
        <div class="col-sm-8 col-lg-7">
            <input class="form-control custom-file-input" name="file" id="file" type="file" form="file-upload-form" />
        </div>
    </div>
    </form>

    <div class="form-group row">
        <div class="col-4 offset-3">
            <button type="submit" name="submit" class="btn btn-outline-success" form="main-form"><?php echo $label['submit-button']; ?></button>
        </div>
    </div>

    </form>

I have added the form attribute to every input and button.我已将form属性添加到每个输入和按钮。 However, the inner form ("file-upload-form") won't submit at all when I add the file.但是,当我添加文件时,内部表单(“file-upload-form”)根本不会提交。

Could it be because this is an auto-submit input, ie the Javascript triggers the AJAX when the file is selected?可能是因为这是一个自动提交的输入,即选择文件时 Javascript 会触发 AJAX? This is the trigger line:这是触发线:

$('#file-upload-form').on('change', function(e){
...

As soon as I move the nested form below the closing </form> tag of the main form, it works.只要我将嵌套表单移动到主表单的结束</form>标记下方,它就可以工作。

If the aesthetic layout can be achieved in any other way, eg the file upload input can appear above the Submit button without nesting the forms, please let me know.如果可以通过任何其他方式实现美学布局,例如文件上传输入可以出现在提交按钮上方而不嵌套表单,请告诉我。

这种布局有效但不美观

这个看起来不错,但不起作用

EDIT: This is the revised Javascript that takes care of the file upload via AJAX.编辑:这是修改后的 Javascript,负责通过 AJAX 上传文件。 I have removed the inner form tags as advised but the input still won't submit.我已按照建议删除了内部form标签,但输入仍然不会提交。

$(function(){
    // listen for input changes (when a file is selected)
    $('#file-upload-input').on('change', function(e){
        //var formData = new FormData();
        // file has been selected, submit it via ajax
        $.ajax({
            type: 'POST',
            url: "/upload_file_ajax.php",
            data: new FormData(this),
            cache: false,
            contentType: false,
            processData: false,
            success: function(data){
                // the upload_file_ajax.php endpoint returns the file name and a status message for the uploaded file
                console.log(data.filename, data.message);
                // we then inject these into the main data form
                var $hiddenInput = $('<input type="hidden" name="uploads[]" value="'+data.filename+'">');
                $('#main-form').append($hiddenInput);

                // show a thumbnail maybe?
                var $thumbnail = $('<img src="/uploaded_files/'+data.filename+'" width="40" height="40" />');
                $("#preview").append($thumbnail);

                $("#status").html(JSON.stringify(data.message));

                // reactivate file upload form to choose another file
                $('#file-upload-input').val('');
            },
            error: function(){
                console.log("error");
            }
        });
    });
}); 

This is what the revised HTML looks like:这是修改后的 HTML 的样子:

<form action="" method="post" enctype="multipart/form-data" id="main-form">
... (other inputs here)...
    <div class="form-group row offset-3 mb-3">
        <div class="col-12" id="preview"></div>
        <div class="col-12" id="status"></div>
    </div>

    <div class="form-group row mb-3 mb-3">
        <label class="col-sm-3 col-lg-3 col-form-label" for="file"><?php echo $label['attach-file']; ?></label>
        <div class="col-sm-8 col-lg-7">
            <input class="form-control custom-file-input" name="file" id="file" type="file" id="file-upload-input" form="file-upload-form" />
        </div>
    </div>

    <div class="form-group row">
        <div class="col-4 offset-3">
            <button type="submit" name="submit" class="btn btn-outline-success" form="main-form"><?php echo $label['submit-button']; ?></button>
        </div>
    </div>

    </form>

Here is how I solved my problem.这是我解决问题的方法。 I found the answer here, on SO, but can't find the link to the post any more.我在 SO 上找到了答案,但再也找不到帖子的链接了。

The problem with uploading a file independently , without submitting the form or without having <form>...</form> tags, is that FormData();独立上传文件,不提交表单或没有<form>...</form>标签的问题是FormData(); does not contain the file as it does when the <form>...</form> tags are present.不像<form>...</form>标签存在时那样包含文件。 So, you need to append the file to it.因此,您需要将文件附加到它。

Here is my entire jQuery code that takes care of the file upload.这是我负责文件上传的整个 jQuery 代码。 On success, it creates additional form input tags containing the uploaded files info, so that I can submit them together with the form.成功后,它会创建包含上传文件信息的额外表单input标签,以便我可以将它们与表单一起提交。 It also creates a thumbnail for each uploaded image, and a Delete button next to the input in case the user changes their mind.它还为每个上传的图像创建一个缩略图,并在input旁边创建一个删除按钮,以防用户改变主意。

$('#file-upload-input').change(function(){
    var file_data = $('#file-upload-input').prop('files')[0];
    var form_data = new FormData();
    // pass the file itself – needed because the input is submitted without <form> tags
    form_data.append('file', file_data);
    // pass website language variable to the PHP processor to load the correct language file
    form_data.append('lang', '<?php echo $lang; ?>');
    $.ajax({
        url: "/ajax_upload_file.php",
        type: "POST",
        data: form_data,
        cache: false,
        contentType: false,
        processData: false,
        success: function(data){
            // the upload_file_ajax.php endpoint returns the file name and a status message for the uploaded file
            console.log(data.filename, data.message);
            // we then inject these into the main data form
            var $hiddenInput = $('<div class="input-group mb-1"><input class="form-control" readonly type="text" name="uploads[]" value="'+data.filename+'" /><input type="button" name="delete_'+data.filename+'" id="delete_'+data.filename+'" value="Delete" class="delete btn btn-outline-danger ms-2" /></div>');
            $('#uploaded_files').append($hiddenInput);
            // show a thumbnail if the uploaded file is an image
            var $thumbnail = $('<img src="/uploaded_files/'+data.filename+'" height="75" id="img_'+data.filename+'" class="me-1" />');
            $("#preview").append($thumbnail);
            // print a status message returned from the PHP processor
            $("#status").html(data.message);
            // reactivate file upload form to choose another file
            $('#file-upload-input').val('');
        },
        error: function(){
            console.log("error");
        }
    });
});

This is the relevant HTML.这是相关的 HTML。 It contains div s for the input s containing the uploaded files names, for the thumbnails (called "preview"), and for the status message returned from the PHP script.它包含div用于包含上传文件名的input 、缩略图(称为“预览”)以及从 PHP 脚本返回的状态消息。

    <div class="form-group row offset-2 mb-3">
        <div class="col-sm-8 col-lg-7" id="uploaded_files">
        </div>
    </div>

    <div class="form-group row offset-2 mb-3">
        <div class="col-12" id="preview"></div>
    </div>

    <div class="form-group row offset-2 mb-3">
        <div class="col-12" id="status"></div>
    </div>

    <div class="form-group row mb-3 mb-3">
        <label class="col-sm-3 col-lg-2 col-form-label" for="file"><?php echo $label['attach-file']; ?></label>
        <div class="col-sm-8 col-lg-7">
            <input class="form-control custom-file-input" name="file" type="file" id="file-upload-input" />
        </div>
    </div>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM