upload-puzzle

1.0.1-8 • Public • Published

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)
})



Readme

Keywords

none

Package Sidebar

Install

npm i upload-puzzle

Weekly Downloads

1

Version

1.0.1-8

License

ISC

Unpacked Size

24.1 kB

Total Files

5

Last publish

Collaborators

  • durand