ファイルのアップロードと検証

14446 ワード

FormIkは簡単にファイルのアップロードを処理する方法を提供しません.私は様々なgithub問題とスタックオーバー議論を見てまともな解決策を見つけました.
ここでは、ファイルのサイズを検証する方法を示します.
リンクhttps://codesandbox.io/s/hardcore-ully-tdk4iu?file=/src/App.js
FormIkのファイルとの作業の背後にある基本的なアイデアは、ファイル入力コンポーネントを制御せずに、選択したファイルにアクセスすることですref . 詳しい情報はこちらhttps://reactjs.org/docs/uncontrolled-components.html#the-file-input-tag
ステップ1:我々はref フォーム内で、そのrefをファイル入力コンポーネントに渡します.
export default function App() {
  const initialValues = {
    files: ""
  };
  const fileRef = useRef(null);
  return (
    <Formik
      initialValues={initialValues}
      validationSchema={Yup.object({
        files: Yup.mixed()
          {/* ... */}
      })}
      onSubmit={(values) => {
        {/* ... */}
      }}
    >
      <Form>
        <FileUpload name="files" fileRef={fileRef} />
        <button type="submit">Submit</button>
      </Form>
    </Formik>
  );
}
ステップ2:内部<FileUpload> コンポーネントを使用するref 次のようになります.
const FileUpload = ({ fileRef, ...props }) => {
  const [field, meta] = useField(props);
  return (
    <div>
      <label htmlFor="files">Choose files</label>{" "}
      <input ref={fileRef} multiple={true} type="file" {...field} />
      {meta.touched && meta.error ? (
        <div style={{ color: "red" }}>{meta.error}</div>
      ) : null}
    </div>
  );
};
ステップ3 :アップロードされたファイルのサイズとファイルのMIMEタイプを次のように検証します.
注:直接使用してファイルにアクセスしているref .
validationSchema={Yup.object({
        files: Yup.mixed()
          .test("is-file-too-big", "File exceeds 10MB", () => {
            let valid = true;
            const files = fileRef?.current?.files;
            if (files) {
              const fileArr = Array.from(files);
              fileArr.forEach((file) => {
                const size = file.size / 1024 / 1024;
                if (size > 10) {
                  valid = false;
                }
              });
            }
            return valid;
          })
          .test(
            "is-file-of-correct-type",
            "File is not of supported type",
            () => {
              let valid = true;
              const files = fileRef?.current?.files;
              if (files) {
                const fileArr = Array.from(files);
                fileArr.forEach((file) => {
                  const type = file.type.split("/")[1];
                  const validTypes = [
                    "zip",
                    "xml",
                    "xhtml+xml",
                    "plain",
                    "svg+xml",
                    "rtf",
                    "pdf",
                    "jpeg",
                    "png",
                    "jpg",
                    "ogg",
                    "json",
                    "html",
                    "gif",
                    "csv"
                  ];
                  if (!validTypes.includes(type)) {
                    valid = false;
                  }
                });
              }
              return valid;
            }
          )
      })}
参考文献
  • https://github.com/jaredpalmer/formik/issues/926
  • https://stackoverflow.com/a/55570763/7358595