upload-puzzle
v1.0.1-8
Published
'Upload multiple chunks'
Downloads
3
Readme
Upload Puzzle is a way to upload files using chunks
npm install upload-puzzle
How to use on client side
import UploadPuzzle from 'upload-puzzle'
const Upload = new UploadPuzzle({
setupURL: '/upload/setup',
uploadChunkURL: '/upload'
})
// handle chunk upload changes
Upload.onChange(response => {
console.log('onChange', response.buffers)
})
// after all chunks has been uploadded
Upload.onComplete(response => {
console.log('onComplete', response.buffers)
})
// on errors
Upload.onError(error => {
console.log('onError', error)
})
//setting file
Upload.setFile(File)
// setting new header
Upload.setHeader({
Authorization: "bearer xxxXXxx"
})
// start uploading
Upload.upload()
How to use on backend
const express = require('express')
const http = require('http')
const app = express()
const fs = require('fs')
const path = require('path')
const formidable = require('formidable')
const cors = require('cors')
const uploads = []
const chunkSizeLimit = 100 * 1000 * 1000;
const s4 = () => {
return Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1);
}
const createUUID = () => {
return s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() + s4() + s4();
}
app.use(cors())
const HTTP_PORT = 5001
app.post('/upload', (req, res) => {
try {
new formidable.IncomingForm().parse(req, (error, fields, files) => {
if (error) {
console.error('Error', error)
res.json({ error })
}
console.log('/upload fields', fields)
// adding file tmp path
uploads[fields.uploadSessionId].chunks[fields.chunkNumber] = files['chunkBlob'].path
console.log(files['chunkBlob'].path)
// saving file type
uploads[fields.uploadSessionId].fileType = fields.fileType
// saving file name
uploads[fields.uploadSessionId].fileName = fields.fileName
// saving file extension
uploads[fields.uploadSessionId].ext = path.extname(fields.fileName)
// increasing number of processed files
uploads[fields.uploadSessionId].numberOfProcessedChunks = uploads[fields.uploadSessionId].numberOfProcessedChunks + 1
// checking if I've processed
if ( uploads[fields.uploadSessionId].numberOfProcessedChunks === uploads[fields.uploadSessionId].numberOfChunks ) {
let fullFile = ''
const filePath = `./files/${fields.uploadSessionId}${uploads[fields.uploadSessionId].ext}`
// creating a file with all chunks
fs.writeFileSync(filePath, fullFile)
for (const chunk of uploads[fields.uploadSessionId].chunks) {
// appending all files
fs.appendFileSync(filePath, fs.readFileSync(chunk))
fs.unlinkSync(chunk)
}
// deleting memory reference
delete uploads[fields.uploadSessionId]
// sending Success API response
res.json({status: 'success'})
} else {
// sending Pendding API response
res.json({status: 'pendding', numberOfProcessedChunks: uploads[fields.uploadSessionId].numberOfProcessedChunks, chunkNumber: fields.chunkNumber})
}
})
} catch (error) {
res.json({error})
}
})
app.post('/upload/setup', (req, res) => {
new formidable.IncomingForm().parse(req, (error, fields, files) => {
console.log('setup fields', fields)
// creating new UUID
let uuid = createUUID()
const numberOfChunks = Math.ceil(fields.fileSize/chunkSizeLimit)
console.log('numberOfChunks', numberOfChunks)
// configuring new upload
uploads[uuid] = {
numberOfChunks,
numberOfProcessedChunks: 0,
uploadSessionId: uuid,
chunks: []
}
// seding Api response
res.json({status: 'success', numberOfChunks, uploadSessionId: uuid})
})
})
app.get('/upload/check/:fileSize', (req, res) => {
if (Math.ceil(req.params.fileSize) <= (chunkSizeLimit * 10)) {
res.json({status: 'success', numberOfChunks: Math.ceil(req.params.fileSize/chunkSizeLimit)})
} else {
res.json({status: 'fail', message: `The file size is too large the limit is 10 MB`})
}
})
app.post('/file-upload', (req, res) => {
try {
const form = new formidable.IncomingForm();
form.parse(req, function (err, fields, files) {
const oldpath = files['file'].path;
const newpath = '/var/www/upload-puzzle/src/server/files/' + files['file'].name;
fs.rename(oldpath, newpath, function (err) {
if (err) throw err;
res.json({status: 'success', message: `File uploadded sucessfully`})
});
})
} catch (error) {
res.json({status: 'fail', error})
}
})
// creating new HTTP Server
const httpServer = http.createServer(app)
// listen
httpServer.listen(HTTP_PORT, '0.0.0.0', () => {
console.log('server running on port ', HTTP_PORT)
})