Search code examples
reactjsgoogle-chromereact-dropzone

Failed- Download Error while using react dropzone with chrome


I am having a strange problem in my application. The desired behavior I am trying to achieve is submitting a form in the browser (I am using react-hook-form), in the submitted form will be some data and there is an option to add files, after submitting the form to the server I am getting a response which contains PDF file. Till now everything was good and I had multiple forms working perfectly (in those forms I still didn't added the option to add files). However, I tried to add react-dropzone to my app for the file upload. Now there might be a few different scenarios:

  1. Not adding any file- I am getting a good response with PDF file inside.
  2. Adding file by clicking the upload component and choosing files with file chooser- I am getting a good response with PDF file inside.
  3. Drag and drop files- I am getting Failed- Download Error , after getting this error I am getting approximately 100 empty temp files downloaded.

Few notes about the error:

  1. It seems that the request reaches the server with all the data inside, and the server do the work of creating a PDF file and saving it on the PC, also the server returns status code 200, so it seems the problem is not with the server.
  2. It seems that the problem occurs only in Chrome( I am using latest version 95.0.4638.69), I tried to do the same on edge and it works.
  3. It seems that this error makes some process on my PC to behave strange or get stuck. Since after getting this error, trying download other files in my app causes the same problem, the only way to fix it is restart the computer (it's not enough to just reload the react app again). Also after getting this error in chrome I am starting getting it on edge.
  4. At first I thought the problem was that I tried to send the files, so I removed the files from the request but the problem is still going.
  5. The console is clear of errors.

Here is my FilesUploadStep in which I am using the dropzone, since it's only the step, I am having a parent component which I will show later ( I removed the styles from the code here, to make it shorter if there is need to add them, please tell me)

const FilesUploadStep = ({ files, handleSetFiles, stepNumber, handleRemoveFile, onSubmit }) => {
const classes = useStyles();

const { control, handleSubmit, formState: { errors } } = useForm({});

const onDropAccepted = useCallback((files) => {
    handleSetFiles(files)
}, [])

const { getRootProps, getInputProps, isDragActive, isDragAccept, isDragReject } = useDropzone({
    accept: 'image/jpeg, image/png, application/vnd.openxmlformats-officedocument.wordprocessingml.document, application/pdf',
    multiple: true,
    onDropAccepted
});

const style = useMemo(() => ({
    ...baseStyle,
    ...(isDragActive ? activeStyle : {}),
    ...(isDragAccept ? acceptStyle : {}),
    ...(isDragReject ? rejectStyle : {})
}), [
    isDragActive,
    isDragReject,
    isDragAccept
]);


return (
    <form id={`form-step-${stepNumber}`} onSubmit={handleSubmit(onSubmit)}>

        <div className={classes.formStepContainer}>
            <div className="container">
                <div {...getRootProps({ style })}>
                    <input {...getInputProps()} />
                    <BackupIcon fontSize="large" />
                    {!isDragActive && <p>"Drag here"</p>}
                    {isDragAccept && <p>"Accept"</p>}
                    {isDragReject && <p>"Reject"</p>}
                </div>
                <div>
                    {files.length > 0 &&
                        <Typography variant="h6" className={classes.title}>
                            {t('form114.filesUpload.subtitle')}
                        </Typography>}
                    <div className={classes.demo}>
                        <List >
                            {files.map((file) =>
                                <ListItem key={`${file.path}`} >
                                    <ListItemAvatar>
                                        <Avatar>
                                            {file.type === "application/vnd.openxmlformats-officedocument.wordprocessingml.document" && <DescriptionIcon />}
                                            {file.type === "application/pdf" && <DescriptionIcon />}
                                            {file.type.startsWith('image') && <ImageIcon />}
                                        </Avatar>
                                    </ListItemAvatar>
                                    <ListItemText
                                        primary={file.name}
                                    />
                                    <ListItemSecondaryAction>
                                        <IconButton edge="end" aria-label="delete" onClick={() => handleRemoveFile(file)}>
                                            <DeleteIcon />
                                        </IconButton>
                                    </ListItemSecondaryAction>
                                </ListItem>
                            )}
                        </List>
                    </div>
                </div>
            </div>
        </div >
    </form>
)}

Here is my parent component with the submit method (since it's pretty big component I tried only to include the relevant code):

const myForm = (props) => {
const classes = useStyles();
const [activeStep, setActiveStep] = useState(0);
const [formValues, setFormValues] = useState(defaultValues);
const [files, setFiles] = useState([])


const handleSetFiles = (files) => {
    console.log("enter", files)
    setFiles(prev => [...prev, ...files])
}

const handleRemoveFile = (file) => {
    setFiles(prev => prev.filter(f => f.path !== file.path))
}

const onSubmit = (data) => {
    console.log("data", data)
    console.log("formValues" + JSON.stringify(formValues))
    if (activeStep === 4) {
        const finalData = {
            ...formValues.step1, ...formValues.step2, ...formValues.step3, paying_company: formValues.paying_company.id,
            known_relationship: convertStringToBoolean(formValues.step3.known_relationship),
            previous_payments_in_tax_year: convertStringToBoolean(formValues.step3.previous_payments_in_tax_year),
            payment_date: convertDateToString(formValues.step3.payment_date),
            previous_payment_date: convertDateToString(formValues.step3.previous_payment_date),
        }

        axios
            .post(process.env.REACT_APP_DJANGO_URL + "/form114/", finalData, {
                contentType: "multipart/form-data",
                responseType: "blob"
                               }
            )
            .then(response => {
                const url = window.URL.createObjectURL(new Blob([response.data]));
                const link = document.createElement('a');
                link.href = url;
                link.setAttribute('download', `Form 114 - ${formValues.paying_company.id}.pdf`); //or any other extension
                document.body.appendChild(link);
                link.click();
             })
            .catch((error) => console.log(error));

    }

    handleNext();
}

const handleNext = () => {
    setActiveStep((prevActiveStep) => prevActiveStep + 1);
};

function getStepFormPart(step) {
    switch (step) {
        case 4:
            return (
                <FilesUploadStep stepNumber={4} onSubmit={onSubmit} files={files} handleSetFiles={handleSetFiles} handleRemoveFile={handleRemoveFile} />
            );
        default:
            return;
    }
}

return (
    <div className={classes.root}>
        <h2 className="title">Form</h2>
        <Divider style={{
            height: "2px",
            backgroundColor: "#FFD400",
            marginTop: "5px"
        }} />
        <BackToOptionsButton />
        <div className={classes.stepperContainer}>

            <Stepper className={classes.stepper} activeStep={activeStep} orientation="vertical">
                {steps.map((label) => (
                    <Step key={label}>
                        <StepLabel classes={{ label: classes.step_label_root }}>
                            {label}
                        </StepLabel>
                        <StepContent>
                            <div className={classes.actionsContainer}>
                                <div>
                                    {activeStep !== 0 &&
                                        <Button
                                            onClick={handleBack}
                                            className={clsx(classes.button, classes.buttonOutlined)}
                                            variant="outlined"
                                        >
                                            {t('buttons.back')}
                                        </Button>
                                    }

                                    <Button
                                        variant="contained"
                                        color="primary"
                                        className={classes.button}
                                        type="submit"
                                        form={`form-step-${activeStep}`}
                                    >
                                        {activeStep === steps.length - 1 ? t('buttons.finish') : t('buttons.next')}
                                    </Button>
                                </div>
                            </div>
                        </StepContent>
                    </Step>
                ))}
            </Stepper>
            <div className={classes.formContainer}>
                {getStepFormPart(activeStep)}
            </div>
        </div>
        {
            activeStep === steps.length && (
                <Paper square elevation={0} className={classes.resetContainer}>
                    <Typography>All steps completed - you&apos;re finished</Typography>
                </Paper>
            )
        }
    </div >
)

}

The error I am getting

Some of the empty temp files I am getting


Solution

  • This problem was only solved after I switched computer. Seems to be something in the operating system or maybe some process that didn't worked as it should have been.