使用 react-hook-form 上传和保存文件列表

Upload and save list of files with react-hook-form

我正在构建一个主要针对使用 Ionic React 的浏览器的网站。 我正在尝试使用 react-hook-form 上传文件列表(以及其他数据)并将它们与其他数据一起保存在 FieldArray 中。

我已经在 answer in Ionic Forum 之后使用 IonButton 和输入实现了文件上传。

 <input
       type="file"
       id="file-upload"
       style={{ display: "none" }}
       onChange={() => { setFile(index);}}/>
  <IonButton
       onClick={() => {openFileDialog();}}
       disabled={files === undefined || files[index] === undefined}>
     <IonLabel>Upload file</IonLabel>
     <IonIcon slot="start" />
   </IonButton>

代码:

function openFileDialog() {
    (document as any).getElementById("file-upload").click();
  }

const setFile = (index: number) => (_event: any) => {
    console.log(`Getting file for index ${index}`);

    let f = _event.target.files![0];

    var reader = new FileReader();

    reader.onload = function () {
      setValue(`files.${index}.file`, reader.result);
    };

    reader.onerror = function () {
      console.log("File load failed");
    };

    reader.readAsDataURL(f);
};

完整示例代码:codesandbox

文件已正确上传,但我无法将其添加到 FieldArray 中的正确字段。文件总是添加到元素 0。我假设这与未在表单中直接修改但在函数 openFileDialog() 中修改的输入有关。结果,input 的 onChange() 函数没有收到正确的 index 值。 是否存在其他错误来源?

一个解决方案是在 IonButton 的 onClick() 方法中等待文件加载,但是在调用 (document as any).getElementById("file-upload").click();.

时我无法发送索引

另一种解决方案可能是只使用一个组件而不是两个组件来上传文件。但是,Ionic 似乎没有这方面的组件。 IonInput type="file" 不起作用。 documentation 令人困惑:“文件”没有出现在 属性 类型的可接受值列表中,但在属性 multiple 和 accepted 的描述中提到了它。

如何正确保存文件?

我发现您的方法存在一些问题,我还删除了将文件读取到 blob 中的操作,在用户实际提交之前您不应该这样做,因为他们可能会删除文件。

第一期 - 您没有将索引传递给此函数

  const setFile = (index: number, _event: any) => {
    methods.setValue(`files[${index}].file` as any, _event.target.files[0]);
    methods.setValue(
      `files[${index}].title` as any,
      _event.target.files[0]?.name
    );
  };

第二个问题,您没有为上传按钮创建唯一标识符,您还需要在那里包含索引

<IonItem>
  <input
    type="file"
    id={`file-upload-${index}`} // <== NEW CODE
    style={{ display: "none" }}
    onChange={(e) => {
      console.log("In input", index);
      setFile(index, e);
    }}
  />
  <IonButton
    onClick={() => {
      openFileDialog(index);  // <== NEW CODE
    }}
    disabled={files === undefined || files[index] === undefined}
  >
    <IonLabel>Upload file</IonLabel>
    <IonIcon slot="start" />
  </IonButton>
</IonItem>

然后您需要 openFileDialog 中的索引,以便您可以单击相应的按钮。

  function openFileDialog(index: any) {
    (document as any).getElementById("file-upload-" + index).click();
  }

在此沙箱中查看完整的解决方案