尝试将React-Admin ImageInput文件转换为base64时错误

发布于 2025-01-30 23:54:52 字数 5261 浏览 1 评论 0原文

之后官方react-admin docs /图像上传。我在Chrome Console日志中偶然发现了此错误:

”在此处输入图像描述

它每次从编辑页面调用更新API方法时显示 代码结构如下:

export const PlayerEdit = () => (
  <Edit>
    <SimpleForm>
      <TextInput source="id" />
      <NumberInput source="active" />
      <TextInput source="name" />
      <TextInput source="email" />
      <ImageInput source="profileImgShow" multiple={true} accept="image/png">
        <ImageField source="src" title="title" />
      </ImageInput>

      <TextInput source="new_password" />
      <TextInput source="repeat_password" />

      <DateInput source="register_date" />
      <DateInput source="createdAt" />
      <DateInput source="updatedAt" />
    </SimpleForm>
  </Edit>
);

我将更新API调用与此助手功能包装,以添加上载功能并促进Base64转换。

export const convertFileToBase64 = (file) => {
  console.log("rawFile", file.rawFile);
  return new Promise((resolve, reject) => {
    const reader = new FileReader();

    reader.onload = () => resolve(reader.result);
    reader.onerror = reject;
    reader.readAsDataURL(file.rawFile);
  });
};

/**
 * For posts update only, convert uploaded image in base 64 and attach it to
 * the `picture` sent property, with `src` and `title` attributes.
 */
const addUploadFeature = (requestHandler) => (resource, params) => {
  //console.log(resource, params);
  if (resource === "players") {
    // notice that following condition can be true only when `<ImageInput source="pictures" />` component has parameter `multiple={true}`
    // if parameter `multiple` is false, then data.pictures is not an array, but single object
    if (params.data.profileImgShow && params.data.profileImgShow.length) {
      // only freshly dropped pictures are instance of File

      const formerPictures = params.data.profileImgShow.filter(
        (p) => !(p.rawFile instanceof File)
      );

      const newPictures = params.data.profileImgShow.filter(
        (p) => p.rawFile instanceof File
      );

      return Promise.all(formerPictures.map(convertFileToBase64))
        .then((base64Pictures) =>
          base64Pictures.map((picture64) => ({
            src: picture64,
            title: `${newPictures.title}`,
          }))
        )
        .then((transformedNewPictures) =>
          requestHandler(resource, {
            ...params,
            data: {
              ...params.data,
              profileImgShow: [...transformedNewPictures, ...formerPictures],
            },
          })
        );
    }
  }
  // for other request types and resources, fall back to the default request handler
  //return requestHandler(type, resource, params);
};

export default addUploadFeature;

这样:

 update: addUploadFeature((resource, params) => {
    //console.log(params);
    return httpClient(`${apiUrl}/${resource}/${params.id}`, {
      method: "PUT",
      body: JSON.stringify(params.data),
    }).then(({ json }) => ({ data: json }));
  }),

但是由于某种原因,Convetfiletobase64从未被打来过,我的猜测是因为 ImageInput组件提供的图像/文件的数组具有类型[对象]而不是[文件] 或[blob]因此,按类型过程的过滤总是失败:

  const newPictures = params.data.profileImgShow.filter(
    (p) => p.rawFile instanceof File
  );

我是在做错事,还是是提供错误类型的文件类型的React-Admin组件? 附件的图像显示了通过以前的图片阵列而不是新模式的结果 因为过滤行返回始终为新图片的空数组,并且只有以前的图表contian从ImageInput收到的文件。

我要重新启动的文件:

{
    "path": "logo192.png",
    "name": "logo192.png",
    "lastModified": 1635067661651,
    "lastModifiedDate": "2021-10-24T09:27:41.651Z",
    "webkitRelativePath": "",
    "size": 12630,
    "type": "image/png"
}

更新:

我在codesandbox.io上编辑了教程示例以重现此问题,奇怪的是,奇怪的imageInput返回了类型[file]而不是[object]的对象,但是两个react和react-dom版本都是^17.0.0在沙盒中,在我的计算机上,我降级到旧版本(17.0.0),但仍然没有运气的rabfile仍然具有[对象]的类型,而不是[file]。

更新2: 我终于注意到,在React-Admin官方文档中,他们使用纱线代替NPM,因此我改用Yarn和Voalla,一切正常。

那是我的package.json文件:

{
  "name": "admin-panel",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@testing-library/jest-dom": "^5.14.1",
    "@testing-library/react": "^13.0.0",
    "@testing-library/user-event": "^13.2.1",
    "prop-types": "^15.8.1",
    "ra-data-json-server": "^4.1.0",
    "react": "^18.1.0",
    "react-admin": "^4.1.0",
    "react-dom": "^18.1.0",
    "react-scripts": "5.0.1",
    "web-vitals": "^2.1.0"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": [
      "react-app",
      "react-app/jest"
    ]
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  }
}

Following the official react-admin docs on how to implement file/image upload. I stumbled upon this error in Chrome console log:

enter image description here

It shows every time I call the update API method from the Edit page
the code structure is as follows:

export const PlayerEdit = () => (
  <Edit>
    <SimpleForm>
      <TextInput source="id" />
      <NumberInput source="active" />
      <TextInput source="name" />
      <TextInput source="email" />
      <ImageInput source="profileImgShow" multiple={true} accept="image/png">
        <ImageField source="src" title="title" />
      </ImageInput>

      <TextInput source="new_password" />
      <TextInput source="repeat_password" />

      <DateInput source="register_date" />
      <DateInput source="createdAt" />
      <DateInput source="updatedAt" />
    </SimpleForm>
  </Edit>
);

and I wrapped the update API call with this helper function to add the upload functionality and facilitate the base64 convertion.

export const convertFileToBase64 = (file) => {
  console.log("rawFile", file.rawFile);
  return new Promise((resolve, reject) => {
    const reader = new FileReader();

    reader.onload = () => resolve(reader.result);
    reader.onerror = reject;
    reader.readAsDataURL(file.rawFile);
  });
};

/**
 * For posts update only, convert uploaded image in base 64 and attach it to
 * the `picture` sent property, with `src` and `title` attributes.
 */
const addUploadFeature = (requestHandler) => (resource, params) => {
  //console.log(resource, params);
  if (resource === "players") {
    // notice that following condition can be true only when `<ImageInput source="pictures" />` component has parameter `multiple={true}`
    // if parameter `multiple` is false, then data.pictures is not an array, but single object
    if (params.data.profileImgShow && params.data.profileImgShow.length) {
      // only freshly dropped pictures are instance of File

      const formerPictures = params.data.profileImgShow.filter(
        (p) => !(p.rawFile instanceof File)
      );

      const newPictures = params.data.profileImgShow.filter(
        (p) => p.rawFile instanceof File
      );

      return Promise.all(formerPictures.map(convertFileToBase64))
        .then((base64Pictures) =>
          base64Pictures.map((picture64) => ({
            src: picture64,
            title: `${newPictures.title}`,
          }))
        )
        .then((transformedNewPictures) =>
          requestHandler(resource, {
            ...params,
            data: {
              ...params.data,
              profileImgShow: [...transformedNewPictures, ...formerPictures],
            },
          })
        );
    }
  }
  // for other request types and resources, fall back to the default request handler
  //return requestHandler(type, resource, params);
};

export default addUploadFeature;

like this:

 update: addUploadFeature((resource, params) => {
    //console.log(params);
    return httpClient(`${apiUrl}/${resource}/${params.id}`, {
      method: "PUT",
      body: JSON.stringify(params.data),
    }).then(({ json }) => ({ data: json }));
  }),

but for some reason the convetFileToBase64 never get called, and my guess that's because
the array of images/files supplied by ImageInput component have the type [Object] instead of [File]
or [Blob] so the filtration by type process always fails:

  const newPictures = params.data.profileImgShow.filter(
    (p) => p.rawFile instanceof File
  );

Am I doing something wrong or it's the react-admin component supplying the wrong type of file?
The attached image shows the result of formerPictures array being passed instead of newPictures
because the filtration line return always empty array for newPictures and only formerPictures contian the file received from ImageInput.

the file I'm reciveing:

{
    "path": "logo192.png",
    "name": "logo192.png",
    "lastModified": 1635067661651,
    "lastModifiedDate": "2021-10-24T09:27:41.651Z",
    "webkitRelativePath": "",
    "size": 12630,
    "type": "image/png"
}

UPDATE:

I edited the tutorial sample on codesandbox.io to reproduce this issue, and oddly enough ImageInput returned an object of type [File] instead of [Object], however both react and react-dom versions were ^17.0.0 in sandbox and 18.0.0 on my machine, I downgraded to the older version (17.0.0) but still no luck rawFile still has the type of [Object] instead of [File] .

Update 2:
I finally noticed that in react-admin official documentation they use yarn instead of npm, so I switched to yarn and voalla everything is working as expected.

That's my package.json file:

{
  "name": "admin-panel",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@testing-library/jest-dom": "^5.14.1",
    "@testing-library/react": "^13.0.0",
    "@testing-library/user-event": "^13.2.1",
    "prop-types": "^15.8.1",
    "ra-data-json-server": "^4.1.0",
    "react": "^18.1.0",
    "react-admin": "^4.1.0",
    "react-dom": "^18.1.0",
    "react-scripts": "5.0.1",
    "web-vitals": "^2.1.0"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": [
      "react-app",
      "react-app/jest"
    ]
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文