【问题标题】:Upload multiple files, picking them one by one, with BootstrapVue b-form-file上传多个文件,一一挑选,使用 BootstrapVue b-form-file
【发布时间】:2021-03-26 13:00:10
【问题描述】:

我在 BootstrapVue 中使用 b-form-file 上传文件,将 multiple 设置为 true 非常适用于多个文件,但是每次我选择一个文件时,它都会删除任何以前添加的文件。而且文件通常会分布在多个文件夹中,所以我需要能够从一个文件夹中选择一个文件,选择它,从另一个文件夹中选择另一个文件,等等。

这是 HTML:

<b-form ref="form" novalidate action="upload" method="post" enctype="multipart/form-data">
    <b-form-file name="file_upload[]" :multiple="true" :file-name-formatter="formatAssetUpload" no-drop placeholder="Click to choose"></b-form-file>
</b-form>

我已经尝试添加

ref="fileUpload" 

到 b-form-file 标记,然后在 formatAssetUpload 函数中设置值,但这不起作用。那里有一个 setFiles 函数,但它似乎没有任何影响。我尝试在提交时捕获表单并手动将文件添加到 formdata 中,但这也不起作用,无论我尝试什么,总是只有最后一个被挑选出来的文件/文件通过后端。

有什么想法吗?

感谢您的帮助! :)

【问题讨论】:

    标签: laravel file-upload vuejs2 multipartform-data bootstrap-vue


    【解决方案1】:

    如果你想记住用户选择的文件对象,你可以使用这个javascript:

    new Vue({
      el: '#app',
      data() {
        return {
          files: [],
          filesAccumulated: []
        }
      },
      methods: {
        onChange(event) {
          this.files.forEach(thisFile => {
            this.filesAccumulated.push(thisFile)
          })       
        },
        onReset() {
            this.filesAccumulated = []
        }
      }
    })
    

    一起使用这个 vue 模板

    <div id="app">
      <b-form-file
        v-model="files"
        multiple plain
        v-on:input="onChange">
      </b-form-file>
      <div>
        <ul>
          <li v-for="thisFile in filesAccumulated">
          {{ thisFile.name }}
          </li>
        </ul>
      </div>
      <b-button v-on:click="onReset">
        Reset
      </b-button>
    </div>
    

    当用户执行选择时,b-form-file vue 组件会发出input 事件。可以拾取文件对象 来自与v-model 指令绑定的变量。见documentation

    看看这个小提琴https://jsfiddle.net/1xsyb4dq/2/,看看代码在起作用。

    一般cmets

    让我在你的代码示例和 b-form-file 组件上做一些 cmets:使用 bootstrap-vue 和 &lt;b-form-file&gt; 不建议使用封闭的表单标签来提交表单。相反,您使用 vue 的 v-model 功能从 vue 的数据对象中获取 file objects

    我在这里创建了一个更全面的例子https://jsfiddle.net/to3q7ags/,但我会一步一步解释:

    v-model 属性的值是一个 vue 数据属性的名称:

    <b-form-file v-model="files" multiple plain></b-form-file>
    

    用户在文件输入字段中点击“浏览”,选择文件并按下确定后,vue data 属性将保存一个文件对象数组:

    new Vue({
      el: '#app',
      data() {
        return {
          files: [] 
          // initially empty, but will be populated after file selection
        }
      }
    })
    

    来自b-form文件documentation

    当没有选择文件时,将返回一个空数组。当一个 选择一个或多个文件,返回值将是一个数组 JavaScript 文件对象实例。

    用户选择文件后,您可以通过单击按钮或更改事件将文件发送到您的服务器。

    <b-button v-on:click="onSubmit">
        Submit
    </b-button>
    

    对应的vue方法是这样的

    methods: {
      onSubmit() {
        // Process each file
        this.files.forEach(thisFile => {
          console.log("Submitting " + thisFile.name)
          // add submit logic here
        }
    }
    

    要提交文件,您需要手动创建一个使用multipart/form-data 编码的http post 请求。这可以通过使用FormData 类来完成。

    const formBody = new FormData()
    formBody.set("formParameter", thisFile)
    

    FormData.set() 方法接受文件 blob 作为参数。然后你可以使用 XMLHttpRequest.send() 或 fetch() 来发送 post 请求:

    fetch(
      "https://yourserver/post",{
        method: 'POST',
        body: formBody})
        .then(response => console.log(response))
    

    现在所有选定的文件都已发布到服务器。用户可以使用相同的表单重复该过程,选择新的文件集并再次按下发布按钮。

    您还可以通过侦听“输入”事件来自动发送表单,而无需使用按钮。拖放也可以。

    【讨论】:

    • 非常感谢迈克尔的帮助!我试过了,但它现在仍然允许我单击并选择一个文件,然后再次单击并选择另一个。例如,也许我在两个单独的文件夹中有两个文件——我需要单击并从文件夹 1 中选择文件 1,然后再次单击并从文件夹 2 中选择文件 2,并添加这两个文件。当我在你添加的小提琴中这样做时,它只会在我每次选择另一个时删除第一个选择,所以我总是只剩下一个文件......知道如何一个一个地选择单个文件,然后得到它们都添加到这个数组中了吗?
    • 无法将元素添加到 v-model 绑定的 'files' 数组中。但是您可以定义另一个数组,并在每次用户选择文件时将文件推送到该数组。看看这个小提琴:jsfiddle.net/1xsyb4dq/2我会把它添加到上面的答案中。如果您喜欢,请“接受”答案。
    猜你喜欢
    • 1970-01-01
    • 2021-06-11
    • 1970-01-01
    • 2015-12-01
    • 2018-04-02
    • 2021-06-29
    • 1970-01-01
    • 2021-11-12
    • 2016-12-23
    相关资源
    最近更新 更多