失败 - 使用 chrome 的 react dropzone 时下载错误
Failed- Download Error while using react dropzone with chrome
我的应用程序遇到了一个奇怪的问题。我想要实现的期望行为是在浏览器中提交一个表单(我正在使用 react-hook-form),在提交的表单中将有一些数据并且可以选择添加文件,在将表单提交到服务器之后我收到包含 PDF 文件的回复。到现在为止一切都很好,我有多种形式可以完美地工作(在这些形式中我仍然没有添加添加文件的选项)。但是,我尝试将 react-dropzone 添加到我的应用程序以进行文件上传。
现在可能有几种不同的情况:
- 未添加任何文件 - 我收到了很好的回复,里面有 PDF 文件。
- 通过单击上传组件并使用文件选择器选择文件来添加文件 - 我收到了很好的响应,其中包含 PDF 文件。
- 拖放文件 - 我收到 失败 - 下载错误,收到此错误后我下载了大约 100 个空的临时文件。
关于错误的几点说明:
- 似乎请求到达服务器时包含所有数据,服务器完成创建 PDF 文件并将其保存在 PC 上的工作,服务器 returns 状态码 200,所以看来问题不在服务器上。
- 好像问题只出现在Chrome(我使用的是最新版本95.0.4638.69),我尝试在edge上做同样的事情,它有效。
- 这个错误似乎使我电脑上的某些进程表现异常或卡住。由于出现此错误后,尝试在我的应用程序中下载其他文件会导致同样的问题,修复它的唯一方法是重新启动计算机(仅仅重新加载反应应用程序是不够的)。此外,在 chrome 中出现此错误后,我开始紧张起来。
- 起初我以为问题是我尝试发送文件,所以我从请求中删除了文件,但问题仍然存在。
- 控制台没有错误。
这是我的 FilesUploadStep,我在其中使用了 dropzone,因为它只是一个步骤,所以我有一个父组件,我将在稍后显示(我从此处的代码中删除了样式,以使其更短,如果有是否需要添加它们,请告诉我)
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>
)}
这是我的带有提交方法的父组件(因为它是相当大的组件,我只尝试包含相关代码):
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're finished</Typography>
</Paper>
)
}
</div >
)
}
The error I am getting
Some of the empty temp files I am getting
这个问题是我换了电脑才解决的。似乎是操作系统中的某些东西,或者可能是某些进程没有正常工作。
我的应用程序遇到了一个奇怪的问题。我想要实现的期望行为是在浏览器中提交一个表单(我正在使用 react-hook-form),在提交的表单中将有一些数据并且可以选择添加文件,在将表单提交到服务器之后我收到包含 PDF 文件的回复。到现在为止一切都很好,我有多种形式可以完美地工作(在这些形式中我仍然没有添加添加文件的选项)。但是,我尝试将 react-dropzone 添加到我的应用程序以进行文件上传。 现在可能有几种不同的情况:
- 未添加任何文件 - 我收到了很好的回复,里面有 PDF 文件。
- 通过单击上传组件并使用文件选择器选择文件来添加文件 - 我收到了很好的响应,其中包含 PDF 文件。
- 拖放文件 - 我收到 失败 - 下载错误,收到此错误后我下载了大约 100 个空的临时文件。
关于错误的几点说明:
- 似乎请求到达服务器时包含所有数据,服务器完成创建 PDF 文件并将其保存在 PC 上的工作,服务器 returns 状态码 200,所以看来问题不在服务器上。
- 好像问题只出现在Chrome(我使用的是最新版本95.0.4638.69),我尝试在edge上做同样的事情,它有效。
- 这个错误似乎使我电脑上的某些进程表现异常或卡住。由于出现此错误后,尝试在我的应用程序中下载其他文件会导致同样的问题,修复它的唯一方法是重新启动计算机(仅仅重新加载反应应用程序是不够的)。此外,在 chrome 中出现此错误后,我开始紧张起来。
- 起初我以为问题是我尝试发送文件,所以我从请求中删除了文件,但问题仍然存在。
- 控制台没有错误。
这是我的 FilesUploadStep,我在其中使用了 dropzone,因为它只是一个步骤,所以我有一个父组件,我将在稍后显示(我从此处的代码中删除了样式,以使其更短,如果有是否需要添加它们,请告诉我)
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>
)}
这是我的带有提交方法的父组件(因为它是相当大的组件,我只尝试包含相关代码):
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're finished</Typography>
</Paper>
)
}
</div >
)
}
The error I am getting
Some of the empty temp files I am getting
这个问题是我换了电脑才解决的。似乎是操作系统中的某些东西,或者可能是某些进程没有正常工作。