Last active
October 3, 2020 11:53
-
-
Save fResult/5ea5bafaa3226b4ec4532efb1a362ab4 to your computer and use it in GitHub Desktop.
FileUpload page
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from 'react'; | |
import { CancelToken } from 'axios' | |
const FileUpload = () => { | |
const [fileList, setFileList] = useState([]) // List of File instance | |
const [sizeAmount, setSizeAmount] = useState('') // sum files size (such as '444.44 MB' or '2.15 GB') | |
const [uploadedSize, setUploadedSize] = useState('') // sum uploaded (such as '444.44 MB' or '2.15 GB') | |
const [fileCount, setFileCount] = useState(0) | |
const [progress, setProgress] = useState(0) // sum uploaded (percent) | |
const [prevLoaded, setPrevLoaded] = useState(0) // previous progressEvent.loaded | |
const [allLoaded, setAllLoaded] = useState(0) // sum all files uploaded | |
const [allBytes, setAllBytes] = useState(0) // sum all files byte | |
const cancelUploadRef = useRef() | |
const { execute: uploadFiles, value, isLoading, error } = useAsync( | |
API.uploadFiles, | |
false | |
) | |
useEffect(() => { | |
if (fileList.length > 0) { | |
const calcFileBytes = (amount, file) => { | |
return amount + file.size | |
} | |
const bytes = Array.prototype.reduce.call(fileList, calcFileBytes, 0) | |
setAllBytes(bytes) | |
setSizeAmount(fileSize(bytes, { fixed: 2, spacer: ' ' }).human('jedec')) | |
setFileCount(fileList.length) | |
} | |
}, [fileList, progress, error, value, setAllBytes]) | |
const handleBeforeUpload = (file) => { | |
fileList.push(file) | |
setFileList([...fileList]) | |
return false | |
} | |
const handleRemoveFile = (selectedFile) => { | |
const idx = fileList.indexOf(selectedFile) | |
const newFileList = fileList.slice() | |
newFileList.splice(idx, 1) | |
setFileList(newFileList) | |
} | |
const asyncForEach = async (array, callback) => { | |
for (let idx = 0; idx < array.length; idx++) { | |
await callback(array[idx], idx, array) | |
} | |
} | |
const handleUploadFiles = async () => { | |
const formData = new FormData() | |
const axiosConfig = { | |
headers: { 'content-type': 'multipart/form-data' }, | |
onUploadProgress: (progressEvent) => { | |
const percent = Math.round((allLoaded / allBytes) * 100) | |
setProgress(percent) | |
percent === 100 && setTimeout(() => setProgress(0), 1000) | |
if (progressEvent.loaded <= progressEvent.total) { | |
const growLoaded = progressEvent.loaded - prevLoaded | |
setPrevLoaded(progressEvent.loaded) | |
const newAllLoaded = allLoaded + growLoaded | |
setAllLoaded(newAllLoaded) | |
const uploadedSize = fileSize(newAllLoaded, { fixed: 2, spacer: ' ' }).human('jedec') | |
setUploadedSize(uploadedSize) | |
} | |
}, | |
cancelToken: new CancelToken((cancel) => { | |
cancelUploadRef.current = cancel | |
}) | |
} | |
await asyncForEach( | |
Array.prototype.map.call(fileList, (f) => f), | |
async (file, idx) => { | |
if (!formData.has('uuid')) { | |
formData.set('uuid', uuid()) | |
} else { | |
const uuid = formData.get('uuid') | |
formData.set('uuid', uuid) | |
} | |
formData.set('import_file', file, file.name) | |
await uploadFiles(formData, axiosConfig) | |
} | |
) | |
} | |
return ( | |
<div> | |
{/*Remove for abbrev */} | |
{progress > 0 ? ( | |
fileList.length > 0 ? ( | |
// AntDesign List - display fileList before start upload | |
<FileList | |
{...{ | |
fileList, | |
sizeAmount, | |
fileCount, | |
onRemoveFile: handleRemoveFile | |
}} | |
/> | |
) : ( | |
// AntDesign Upload Dragger - for select multiple files before upload | |
<UploadInput | |
{...{ | |
fileList, | |
onBeforeUpload: handleBeforeUpload | |
}} | |
/> | |
) | |
) : ( | |
// AntDesign Progress | |
<UploadProgress | |
{...{ progress, fileCount, uploadedSize, sizeAmount, willCancel }} | |
/> | |
)} | |
<ActionButtons> | |
{/** such as... | |
* Start Upload, | |
* Stop Upload, | |
* Confirm Stop | |
* Cancel Stop | |
* (dynamic in various above components) | |
**/} | |
</ActionButtons> | |
</div> | |
); | |
}; | |
export default FileUpload; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment