0

I am trying to push to the data array the object with the file and file base64 format in getBase64. But when I console log data array it is empty, also I can turn file into base64 format. But I don't understand why the push method in getBase64 doesn't work. How do I get bot the file and file base 64. enter image description here

export default function UploadDoc({ setInputs }) {
  function beforeUpload(file) {
    const isRightType =
      file?.type === "application/pdf" ||
      file?.type === "application/xlsx" ||
      file?.type === "image/jpeg" ||
      file?.type === "application/csv" ||
      file?.type === "text/plain";
    if (!isRightType) {
      message.error("You can only upload PDF, TXT, JPEG, CSV or XLSX  files!");
    }
    const isLt2M = file?.size / 1024 / 1024 < 2;
    if (!isLt2M) {
      message.error("PDF must be smaller than 2MB!");
    }
    setFileList((state) => (state ? [...state, file] : [file]));
    return isRightType && isLt2M;
  }

  const overrideRequest = ({ file, onSuccess, onError }) => {
    // <Upload/> renders another component (rc-upload) as its child which handles the actual AJAX upload.
    // You can override this behaviour by passing a customRequest prop to <Upload/>
    const isRightType =
      file?.type === "application/pdf" ||
      file?.type === "image/jpeg" ||
      file?.type === "application/csv" ||
      file?.type === "text/plain";
    if (isRightType) {
      setTimeout(() => {
        onSuccess("ok");
      }, 1);
    } else {
      setTimeout(() => {
        onError("ok");
      }, 1);
    }
  };

 const getBase64 = (file) =>
    new Promise((resolve) => {
      // turns file data in loggable and readable data from javascript
      const reader = new FileReader();
      reader.onloadend = () => resolve(reader.result);
      reader.readAsDataURL(file);
    });

  const dispatch = useDispatch();
  const fileList = useSelector((state) => state.filesFileListReducer);

  const handleUploadChange = (info) => {
    if (info.file.status === "error") {
      console.log("error", info.file);
    }

   if (info.file.status === "done") {
      // Get this url/data from response in real world.

      const arr = [];

      info.fileList.forEach(async (file) => {
        const fileInfo = await getBase64(file.originFileObj);
        const infoOnUploadedFile = { base64: fileInfo, fileObj: file };
        console.log("file info", infoOnUploadedFile);
        arr.push(infoOnUploadedFile);
      });
      console.log("data", arr);
      
    }
  };

  return (
    <Upload
      {...{
        multiple: true,
        beforeUpload: (file) => beforeUpload(file),
        accept: ".txt, .csv, .jpeg, .pdf",
        customRequest: (info) => overrideRequest(info),
        onChange: (info) => handleUploadChange(info),
        onRemove: (file) => {
          const newFileList = fileList?.filter(
            (fileGrp) => fileGrp.fileObj !== file
          );
          dispatch(setFileList(newFileList));
          setInputs((state) => ({
            ...state,
            docs: newFileList && newFileList.map((file) => file?.fileBase64),
          }));
        },
      }}
    >
      <Button icon={<UploadOutlined />} style={{ width: "100px" }} />
    </Upload>
  );
}
jps
  • 20,041
  • 15
  • 75
  • 79
FaFa
  • 358
  • 2
  • 16
  • Does this answer your question? [How to convert file to base64 in JavaScript?](https://stackoverflow.com/questions/36280818/how-to-convert-file-to-base64-in-javascript) – Elikill58 Aug 26 '21 at 06:10
  • Thank you but even if I turn the function in a promise, it doesn't push to in the array. So, I couldn't solve the problem – FaFa Aug 26 '21 at 06:18
  • Oh ok. Do you see the log before pushing in array ? It can be because of async operation. Have to try to log the array just after pushing into in ? – Elikill58 Aug 26 '21 at 06:37
  • Still the same problem. It doesn't add. I console log outside but it looks empty, but I change and save, without refreshing the page, I can see the data. – FaFa Aug 26 '21 at 06:54
  • And if you replace the datapush but something like that: `data.push({ base64: fileBase64, fileObj: file });` ? – Elikill58 Aug 26 '21 at 07:02
  • I changed like this ```if (info.file.status === "done") { // Get this url/data from response in real world. console.log("file list", info.fileList); const data = info.fileList.map((file) => { const obj = getBase64(file.originFileObj, (fileInfo) => { const infoOnUploadedFile = { base64: fileInfo, fileObj: file }; console.log("file info", infoOnUploadedFile); return infoOnUploadedFile; }); console.log("obj", obj); return obj; });``` but the obj const is undefined – FaFa Aug 26 '21 at 07:27
  • That's normal, the code that print obj is called before the getBase64 function return the value. You can use async/await method to do it. I will make an anwser – Elikill58 Aug 26 '21 at 07:53
  • I tried to use await/async with getBase64 but it was the same undefined, maybe I was writing wrongly – FaFa Aug 26 '21 at 07:58
  • In your last edit you added [solved] to the title and changed the code. Please do not 'fix' the code in your question, because then the question and answer don't make sense anymore. Also don't add [solved], instead just accept the answer by clicking on the check-mark if it really answered the question. – jps Aug 26 '21 at 09:06

1 Answers1

1

You are trying to get an object before his availability.

Such as you want to get the value but directly, You can use async/await feature (wiki).

For you, something like this will fix it :

const getBase64 = (blob: Blob) => {
  return new Promise((resolve) => {
    const reader = new FileReader()
    reader.onloadend = () => resolve(reader.result)
    reader.readAsDataURL(blob) // read blob
  })
}

const obj = await getBase64(resBlob); // wait until method not finished
// now you can check if obj is defined and push it into array
Elikill58
  • 4,050
  • 24
  • 23
  • 45
  • I can't push the base64 in the array. The array is still empty. ``` const arr = []; info.fileList.forEach(async (file) => { const fileInfo = await getBase64(file.originFileObj); const infoOnUploadedFile = { base64: fileInfo, fileObj: file }; console.log("file info", infoOnUploadedFile); arr.push(infoOnUploadedFile); }); console.log("data", arr);``` – FaFa Aug 26 '21 at 08:23
  • and if you log the obj directly ? – Elikill58 Aug 26 '21 at 08:24
  • I edited my answer with the current state – FaFa Aug 26 '21 at 08:25
  • I need to get the more than one file form the ant design upload form. So I need to store them somehow – FaFa Aug 26 '21 at 08:37