【问题标题】:NodeJS/Express: How can I submit a form by associating multiple input text fields with each of its own file upload?NodeJS/Express:如何通过将多个输入文本字段与每个自己的文件上传相关联来提交表单?
【发布时间】:2021-05-24 17:23:27
【问题描述】:

我正在开发一个 NodeJS/Express 应用程序,我必须在用户输入后提交表单。

可能有一个或一百万个input type text 字段,这取决于用户。每个文本字段都有自己的input type file,允许用户选择上传文件。

假设用户决定提交 3 条数据,因此他选择了 3 个文本字段:textField1, textFieldd2, and textField3。这些文本字段中的每一个都有自己的文件上传字段:fileFieldFortext1, fileFieldFortext2, and fileFieldFortext3。现在,他是上传文件还是将其留空,完全取决于他。

场景 1:当他决定为所有 3 个文本字段上传文件时:

<input type="text" name="textContent" />
<input type="file" name="fileInput" />

<input type="text" name="textContent" />
<input type="file" name="fileInput" />

<input type="text" name="textContent" />
<input type="file" name="fileInput" />

const textContent = req.body.textContent;
const fileData = req.files.fileInput;
 
textContent output: an array of all the texts. ['text1', 'text2', 'text3']
fileData output: an array of objects of all the file data. [ {'fileFortext1'}, {'fileFortext2'}, {'fileFortext3'} ]

我可以根据他们的index 轻松关联他们。它完美地工作。但问题出现在场景 2 中。

场景 2:当他决定不上传一两个文件时:

<input type="text" name="textContent" />
<input type="file" name="fileInput" /> // leaves it empty

<input type="text" name="textContent" />
<input type="file" name="fileInput" />

<input type="text" name="textContent" />
<input type="file" name="fileInput" />

const textContent = req.body.textContent;
const fileData = req.files.fileInput;

textContent output: an array of all the texts. ['text1', 'text2', 'text3']
fileData output: an array of objects of all the file data. [ {'fileFortext2'}, {'fileFortext3'} ].

现在我无法根据索引值关联它们,因为用户没有为第一个上传任何文件。

如何在我的后端得到这样的输出:[ {}, {'fileFortext2'}, {'fileFortext3'} ],第一个是空对象?

如何将每个文本字段与其自己的文件上传输入相关联?

我是否以错误的方式接近它?

请注意,我没有使用 AJAX 提交表单。这是直接提交。

【问题讨论】:

    标签: javascript node.js express


    【解决方案1】:

    这似乎可行,在服务器端使用 mutlerupload.any() 中间件。您可能希望使其适应您的特定设置。请注意,为方便起见,您似乎可以将匹配的textfile inputs 命名为相同的name,因为它们是不同的内容类型。

    <input type="text" name="1" />
    <input type="file" name="1" />
    
    <input type="text" name="2" />
    // No file here
    
    <input type="text" name="3" />
    <input type="file" name="3" />
    

    这是你在服务器端会得到的:

    req.body = { '1': 'text1 value', '2': 'text2 value', '3': 'text3 value' }
    req.files = [
        { fieldname: '1', /* Other properties */ },
        { fieldname: '3', /* Other properties */ }
    ]
    

    然后您可以根据输入名称映射文本和文件:

    var combined = Object.keys(req.body).map(function (key) {
        let fileIndex = req.files.findIndex(file => file.fieldname == key);
        return { text: req.body[key], file: fileIndex >= 0 ? req.files[fileIndex] : undefined }
    })
    
    console.log(combined)
    
    //console output
    [
      { text: 'text1 value', file: { fieldname: '1', /* Other properties */ } },
      { text: 'text2 value', file: undefined },
      { text: 'text3 value', file: { fieldname: '3', /* Other properties */ } }
    ]
    

    【讨论】:

    • 嘿伙计。谢谢你的时间。我以前用过Multer。但这似乎太复杂了。但我会再检查一次。关于您提供的解决方案,如果只有确切数量的字段并且我对 name 值进行硬编码,我就可以做到这一点。但无法知道用户是想提交一个文本字段及其文件还是一千个。
    • 好的。请注意,虽然您实际上不需要提前知道确切的字段数量,但您需要能够在客户端动态生成输入名称。
    • 兄弟。多谢。它工作得很好。虽然我不得不稍作调整,但它奏效了。谢谢老兄。
    【解决方案2】:

    如果您知道预渲染中的字段,则可以使用 express 中的字段数组:

    const textFields = ["textField1", "textField2", "textField3"];
    

    使用该数组生成字段以呈现表单:

    <input type="text" name="textContent[textField1]" />
    <input type="file" name="fileInput[textField1]" />
    
    <input type="text" name="textContent[textFieldd2]" />
    <input type="file" name="fileInput[textFieldd2]" />
    
    <input type="text" name="textContent[textField3]" />
    <input type="file" name="fileInput[textField3]" />
    

    然后,当您收到来自 Express 的提交数据时,在循环中使用相同的数组,因为您可以通过这种方式获取值:

    for (let i = 0; i < textFields.length; i += 1) {
      console.log('INPUT VALUE: textContent ${textFields[i]}:>> ', req.body.textContent[textFields[i]]);
      if(textFields[i] in req.body.fileInput){
        console.log('FILE VALUE: fileInput ${textFields[i]}:>> ', req.body.fileInput[textFields[i]]);
      }
    }
    

    【讨论】:

    • 嘿。谢谢你的时间。你能告诉我你知道预渲染中的字段是什么意思吗?基本上,表单默认有 1 个文本字段和一个文件上传。有一个附加文本字段和文件上传的按钮。用户可以添加他们想要的任何号码。然后他填写数据并提交。
    • 我的解决方案在这种情况下不起作用,抱歉。
    猜你喜欢
    • 2012-09-16
    • 2018-11-08
    • 1970-01-01
    • 2018-11-06
    • 2019-04-10
    • 2017-11-22
    • 1970-01-01
    • 2010-12-14
    • 2013-06-05
    相关资源
    最近更新 更多