I am using react-dropzone for image upload. Everything is working fine. Validation for image size is also working fine. But I could not check the dimension for image. I want to validate the image's width and height to enforce user to upload the image in between those specified width and height. I tried image.addEventListener('load')
but this is not working.
Here is what I have done
export const UploadField = ({ preview, label, uploadProps, ...props }) => {
const {
input: { onChange },
disabled
} = props;
const {
isDragActive,
getRootProps,
getInputProps,
isDragReject,
rejectedFiles
} = useDropzone({
onDrop: files => {
onChange(
files.map(file => {
const image = new Image();
image.addEventListener("load", () => {
console.log("image", image);
});
return Object.assign(file, {
preview: URL.createObjectURL(file)
});
})
);
},
...uploadProps
});
const isFileTooLarge =
rejectedFiles.length > 0 && rejectedFiles[0].size > uploadProps.maxSize;
const files = props.input.value;
if (disabled) {
return null;
}
return (
<>
{label && <Label>{label}</Label>}
<DropzoneContainer {...getRootProps()}>
<input {...getInputProps()} />
{!isDragActive && "Click here or drop a file to upload!"}
{isDragActive && !isDragReject && "Drop it like it's hot!"}
{isDragReject && "File type not accepted, sorry!"}
{isFileTooLarge && (
<div className="text-danger mt-2">File is too large.</div>
)}
</DropzoneContainer>
<div>
{files && files !== undefined ? (
<>
<Preview files={files} isLocal />
</>
) : (
<Preview files={preview} isLocal={false} />
)}
</div>
</>
);
};
export default UploadField;
UploadField.defaultProps = {
uploadProps: {
accept: "image/*",
multiple: false,
minSize: 0,
maxSize: 5242880
}
};
const DropzoneContainer = styled.div`
width: 100%;
padding: 14px;
border-width: 2px;
border-radius: 2px;
border-color: ${props => getColor(props)};
border-style: dashed;
background-color: #fafafa;
color: #bdbdbd;
outline: none;
transition: border 0.24s ease-in-out;
`;
const getColor = props => {
if (props.isDragAccept) {
return "#00e676";
}
if (props.isDragReject) {
return "#ff1744";
}
if (props.isDragActive) {
return "#2196f3";
}
return "#eeeeee";
};
I am using react-dropzone for image upload. Everything is working fine. Validation for image size is also working fine. But I could not check the dimension for image. I want to validate the image's width and height to enforce user to upload the image in between those specified width and height. I tried image.addEventListener('load')
but this is not working.
Here is what I have done
export const UploadField = ({ preview, label, uploadProps, ...props }) => {
const {
input: { onChange },
disabled
} = props;
const {
isDragActive,
getRootProps,
getInputProps,
isDragReject,
rejectedFiles
} = useDropzone({
onDrop: files => {
onChange(
files.map(file => {
const image = new Image();
image.addEventListener("load", () => {
console.log("image", image);
});
return Object.assign(file, {
preview: URL.createObjectURL(file)
});
})
);
},
...uploadProps
});
const isFileTooLarge =
rejectedFiles.length > 0 && rejectedFiles[0].size > uploadProps.maxSize;
const files = props.input.value;
if (disabled) {
return null;
}
return (
<>
{label && <Label>{label}</Label>}
<DropzoneContainer {...getRootProps()}>
<input {...getInputProps()} />
{!isDragActive && "Click here or drop a file to upload!"}
{isDragActive && !isDragReject && "Drop it like it's hot!"}
{isDragReject && "File type not accepted, sorry!"}
{isFileTooLarge && (
<div className="text-danger mt-2">File is too large.</div>
)}
</DropzoneContainer>
<div>
{files && files !== undefined ? (
<>
<Preview files={files} isLocal />
</>
) : (
<Preview files={preview} isLocal={false} />
)}
</div>
</>
);
};
export default UploadField;
UploadField.defaultProps = {
uploadProps: {
accept: "image/*",
multiple: false,
minSize: 0,
maxSize: 5242880
}
};
const DropzoneContainer = styled.div`
width: 100%;
padding: 14px;
border-width: 2px;
border-radius: 2px;
border-color: ${props => getColor(props)};
border-style: dashed;
background-color: #fafafa;
color: #bdbdbd;
outline: none;
transition: border 0.24s ease-in-out;
`;
const getColor = props => {
if (props.isDragAccept) {
return "#00e676";
}
if (props.isDragReject) {
return "#ff1744";
}
if (props.isDragActive) {
return "#2196f3";
}
return "#eeeeee";
};
Share
Improve this question
asked Jan 16, 2020 at 1:41
SerenitySerenity
4,0548 gold badges49 silver badges96 bronze badges
2 Answers
Reset to default 10You never set the src
for the image so your event handler never fires. Try setting image.src = URL.createObjectURL(file)
. Once the file loads, your 'load' handler will fire.
Try changing the contents of your onDrop
callback to include this:
const filteredImages = [];
let counter = 0;
files.map(file => {
const image = new Image();
image.addEventListener('load', () => {
console.log(`${image.width}x${image.height}`)
// only select images within width/height limits
if (image.width < WIDTH_LIM && image.height < HEIGHT_LIM) {
filteredImages.push(image)
}
// increment counter for each image we go through
counter += 1;
// if we have gone through all the files, handle the ones that
// made it through the filter using `handleImages` function
if (counter === files.length) handleImages(filteredImages);
});
image.src = URL.createObjectURL(file)
})
If you want to validate dimensions before onDrop
, you can use getFilesFromEvent
and validator
callbacks like below.
Pros
As with errors such as maxSize and accept, you can get files that are stuck in validation for dimention from rejectedFiles
.
Cons f you are using typescript, you have to eliminate the type error with any type.
const {
isDragActive,
getRootProps,
getInputProps,
isDragReject,
rejectedFiles
} = useDropzone({
getFilesFromEvent: async (event) => {
const files = event.target.files || event.dataTransfer.files
const promises = []
for (let index = 0; index < files.length; index++) {
const file = files[index]
const promise = new Promise((resolve, reject) => {
const image = new Image()
let url: string
image.onload = function () {
file.width = image.width
file.height = image.height
resolve(file)
}
url = URL.createObjectURL(file)
image.src = url
})
promises.push(promise)
}
return await Promise.all(promises)
},
validator: (file) => {
// You can access width/height properties
if(file.width < MIN_WIDTH) {
return {
code: "small-width",
message: `Image width must be greater than ${MIN_WIDTH}`,
}
}
return null
}
});