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

fa_*_*a__ 1 reactjs ionic-framework react-hook-form

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

我已经按照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>
Run Code Online (Sandbox Code Playgroud)

代码:

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);
};
Run Code Online (Sandbox Code Playgroud)

完整示例代码:codesandbox

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

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

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

如何正确保存文件?

Aar*_*ers 6

我发现您的方法存在一些问题,我还将文件的读取删除到了 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
    );
  };
Run Code Online (Sandbox Code Playgroud)

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

<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>
Run Code Online (Sandbox Code Playgroud)

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

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

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