Skip to content

Commit

Permalink
feat(FileUploaderDropContainer): validate filetypes from OS file pick…
Browse files Browse the repository at this point in the history
…er (#6868)

* feat(FileUploaderDropContainer): validate filetypes from OS file picker

* docs(drop-container): add file type validation logic

* chore: lint

* docs(drag-and-drop-file-uploader): add file type validation logic

Co-authored-by: Alessandra Davila <aledavila@ibm.com>
  • Loading branch information
emyarod and Alessandra Davila committed Sep 22, 2020
1 parent f9b1030 commit d7ddb44
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 28 deletions.
41 changes: 29 additions & 12 deletions packages/react/examples/drag-and-drop-file-uploader/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@ const { prefix } = settings;

function ExampleDropContainerApp(props) {
const [files, setFiles] = useState([]);
const handleDrop = e => {
const handleDrop = (e) => {
e.preventDefault();
};
const handleDragover = e => {
const handleDragover = (e) => {
e.preventDefault();
};
useEffect(() => {
Expand All @@ -38,7 +38,7 @@ function ExampleDropContainerApp(props) {
document.removeEventListener('dragover', handleDragover);
};
}, []);
const uploadFile = async fileToUpload => {
const uploadFile = async (fileToUpload) => {
// file size validation
if (fileToUpload.filesize > 512000) {
const updatedFile = {
Expand All @@ -49,8 +49,25 @@ function ExampleDropContainerApp(props) {
errorSubject: 'File size exceeds limit',
errorBody: '500kb max file size. Select a new file and try again.',
};
setFiles(files =>
files.map(file =>
setFiles((files) =>
files.map((file) =>
file.uuid === fileToUpload.uuid ? updatedFile : file
)
);
return;
}
// file type validation
if (fileToUpload.invalidFileType) {
const updatedFile = {
...fileToUpload,
status: 'edit',
iconDescription: 'Delete file',
invalid: true,
errorSubject: 'Invalid file type',
errorBody: `"${fileToUpload.name}" does not have a valid file type.`,
};
setFiles((files) =>
files.map((file) =>
file.uuid === fileToUpload.uuid ? updatedFile : file
)
);
Expand All @@ -73,8 +90,8 @@ function ExampleDropContainerApp(props) {
status: 'complete',
iconDescription: 'Upload complete',
};
setFiles(files =>
files.map(file =>
setFiles((files) =>
files.map((file) =>
file.uuid === fileToUpload.uuid ? updatedFile : file
)
);
Expand All @@ -86,8 +103,8 @@ function ExampleDropContainerApp(props) {
status: 'edit',
iconDescription: 'Remove file',
};
setFiles(files =>
files.map(file =>
setFiles((files) =>
files.map((file) =>
file.uuid === fileToUpload.uuid ? updatedFile : file
)
);
Expand All @@ -99,8 +116,8 @@ function ExampleDropContainerApp(props) {
iconDescription: 'Upload failed',
invalid: true,
};
setFiles(files =>
files.map(file =>
setFiles((files) =>
files.map((file) =>
file.uuid === fileToUpload.uuid ? updatedFile : file
)
);
Expand All @@ -110,7 +127,7 @@ function ExampleDropContainerApp(props) {
const onAddFiles = useCallback(
(evt, { addedFiles }) => {
evt.stopPropagation();
const newFiles = addedFiles.map(file => ({
const newFiles = addedFiles.map((file) => ({
uuid: uid(),
name: file.name,
filesize: file.size,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,23 +43,28 @@ function FileUploaderDropContainer({
* @param {Event} event - Event object, used to get the list of files added
*/
function validateFiles(event) {
if (event.type === 'drop') {
const transferredFiles = [...event.dataTransfer.files];
if (!accept.length) {
return transferredFiles;
}
const acceptedTypes = new Set(accept);
return transferredFiles.filter(({ name, type: mimeType = '' }) => {
const fileExtensionRegExp = new RegExp(/\.[0-9a-z]+$/, 'i');
const hasFileExtension = fileExtensionRegExp.test(name);
if (!hasFileExtension) {
return false;
}
const [fileExtension] = name.match(fileExtensionRegExp);
return acceptedTypes.has(mimeType) || acceptedTypes.has(fileExtension);
});
const transferredFiles =
event.type === 'drop'
? [...event.dataTransfer.files]
: [...event.target.files];
if (!accept.length) {
return transferredFiles;
}
return [...event.target.files];
const acceptedTypes = new Set(accept);
return transferredFiles.reduce((acc, curr) => {
const { name, type: mimeType = '' } = curr;
const fileExtensionRegExp = new RegExp(/\.[0-9a-z]+$/, 'i');
const hasFileExtension = fileExtensionRegExp.test(name);
if (!hasFileExtension) {
return acc;
}
const [fileExtension] = name.match(fileExtensionRegExp);
if (acceptedTypes.has(mimeType) || acceptedTypes.has(fileExtension)) {
return acc.concat([curr]);
}
curr.invalidFileType = true;
return acc.concat([curr]);
}, []);
}

function handleChange(event) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,24 @@ const ExampleDropContainerApp = (props) => {
return;
}

// file type validation
if (fileToUpload.invalidFileType) {
const updatedFile = {
...fileToUpload,
status: 'edit',
iconDescription: 'Delete file',
invalid: true,
errorSubject: 'Invalid file type',
errorBody: `"${fileToUpload.name}" does not have a valid file type.`,
};
setFiles((files) =>
files.map((file) =>
file.uuid === fileToUpload.uuid ? updatedFile : file
)
);
return;
}

// simulate network request time
const rand = Math.random() * 1000;
setTimeout(() => {
Expand Down Expand Up @@ -87,6 +105,7 @@ const ExampleDropContainerApp = (props) => {
filesize: file.size,
status: 'uploading',
iconDescription: 'Uploading',
invalidFileType: file.invalidFileType,
}));
// eslint-disable-next-line react/prop-types
if (props.multiple) {
Expand Down

0 comments on commit d7ddb44

Please sign in to comment.