diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..2392d2e --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 DEEPAK-SUTHAR + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..29e22a6 --- /dev/null +++ b/README.md @@ -0,0 +1,165 @@ +# Load Stream + +[![npm version](https://badge.fury.io/js/load-stream.svg)](https://www.npmjs.com/package/load-stream) +[![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://opensource.org/licenses/MIT) + +## Description + +Load Stream is a versatile package that facilitates the uploading of large files to a server in chunks. The package provides both server-side (`load-stream`) and client-side (`loadstream-client`) components. It utilizes HTTP short polling to break files into chunks and send them to the server, providing multiple listeners for events like progress, completion, and errors. + +### Features + +- Efficient file uploading with chunking +- HTTP short polling for improved performance +- Multiple event listeners: onprogress, onload, onerror +- Methods for stopping and resuming uploads + +## Installation + +### Server-Side (load-stream) + +Install the package using npm: + +```bash +npm install load-stream +``` + +### Integrate it into your server with Express: + +```bash +const loadStream = require('load-stream'); +const express = require('express'); +const app = express(); + +/* cb function to provide and modify the fileName and destination(where to save file) + this cb function expect an argument which contains file information and current uploading directory. +Example: + file-> { + fileName:'hello.png', + fileSize:1242, + destination:'/' //default destination + } +*/ +const cb = (file) => { + return { + fileName: Date.now() + file.fileName, + destination: '/public/uploads' + } +} +//creating instance of loadStream +let loader = new loadStream(cb); + +//use this loadStream instance as middleware to handle and make http requests +app.use(loader.load()); +//on Error +loader.onerror = (e) => { + console.log(e); +} +``` + + + +### Client-Side (CDN) + +You can include the client-side library via CDN in your HTML file: + +```bash + + + +``` + + + +### Client-Side (loadstream-client) +To include client side script in React.Js/Next.Js etc + +```bash +npm install loadstream-client +``` + +### Integrate it into your client side: +```bash +import loadStream from 'loadstream-client' +``` +```bash +/* + const url='http://localhost:5000'; // url is server's host url +*/ +let loader = new loadStream({ url }) // url is required* + + const uploadFile = async (file) => { + try { + loader.upload(file); + + loader.onprogress = (event) => { + console.log(event.progress);// progress Example: to use in progress bar + console.log(event.time); // Expected time remains in uploading file (in seconds) + console.log(event.speed);// Uploading speed (in bytes/sec) + } + + loader.onload = () => { + console.log("Completed"); + } + + loader.onerror = (event) => { + console.log(event.error); + } + + const resumeUpload = ()=>{ + loader.resume(); // returns true if resumed else false + } + + const pauseUpload = ()=>{ + loader.stop();// returns true if paused else false + } + + } catch (error) { + console.error("Upload error:", error); + } +``` + +# Contributing + +We welcome contributions! Your contribution means to us. + +# License +This project is licensed under the MIT License - see the LICENSE file for details. diff --git a/package.json b/package.json index 6ebbdac..f1e790b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "load-stream", - "version": "1.0.2", + "version": "1.0.3", "description": "A npm package to upload files as chunk ", "main": "src/index.js", "scripts": { diff --git a/src/index.ts b/src/index.ts index 8b28061..6c96b5d 100644 --- a/src/index.ts +++ b/src/index.ts @@ -136,10 +136,18 @@ class StreamLoader { fileInfo['chunksize'] = chunksize as number; fileInfo['transferedSize'] = 0; let userId: string = uuidv4(); - fileInfo['writeStream'] = fs.createWriteStream(path.join((fileInfo['destination'] as string) + '/' + (fileInfo['fileName'] as string))).on('ready', () => { + fileInfo['writeStream'] = fs.createWriteStream(path.join(path.resolve() + (fileInfo['destination'] as string) + '/' + (fileInfo['fileName'] as string))).on('ready', () => { this.#fileInfoStore[userId] = fileInfo; - res.json({ handshake: true, userId }); - }).on('error', (err) => { + res.json({ + handshake: true, + userId, info: + { + file: fileInfo.fileName, + size: fileInfo.fileSize, + destination: fileInfo.destination + } + }); + }).on('error', (err: Error) => { this.onerror({ error: err }); res.json({ handshake: false, error: err }); }); @@ -196,4 +204,4 @@ class StreamLoader { export default StreamLoader; -module.exports = StreamLoader; \ No newline at end of file +module.exports = StreamLoader; diff --git a/src/static/js/loadStream.js b/src/static/js/loadStream.js index 95838e4..3c5673b 100644 --- a/src/static/js/loadStream.js +++ b/src/static/js/loadStream.js @@ -1,4 +1,4 @@ -class loadStream { +class LoadStream { //options for transfer file #options = { method: 'http', @@ -21,7 +21,6 @@ class loadStream { * @param {Object} options {uploadMethod:http|websocket,ChunkSize} */ constructor(options = null) { - this.file = file; if (options) { this.#options.method = options.method ? options.method : 'http'; this.#options.chunksize = options.chunksize ? options.chunksize : 1024 * 1024; @@ -33,23 +32,28 @@ class loadStream { * @param {File|Blob|String} file File to Upload */ async upload(file) { - this.file = file; - this.#fileSize = this.file.size; - if (this.#fileSize > 0) { - if (this.#options.method === 'http') { - let res = await this.#handShake(); - if (res.handshake) { - this.#userId = res.userId; - this.#uploadFile(); - } else { - if (this.onerror) - this.onerror({ error: res.error || "Something Wrong During Handshaking!" }); + return new Promise(async (resolve, reject) => { + this.file = file; + this.#fileSize = this.file.size; + if (this.#fileSize > 0) { + if (this.#options.method === 'http') { + let res = await this.#handShake(); + if (res.handshake) { + this.#userId = res.userId; + this.#uploadFile(); + resolve({ success: true, info: res.info }); + } else { + if (this.onerror) + this.onerror({ error: res.error || "Something Wrong During Handshaking!" }); + resolve({ success: false, error: res.error || "Something Wrong During Handshaking!" }) + } + } else if (this.#options.method === 'websocket') { + // let socket = io({ path: '/loadStream.io' }); + resolve({ success: false, error: "Websocket Currently Unavalible!" }) + console.log("Currently Unavalible!"); } - } else if (this.#options.method === 'websocket') { - // let socket = io({ path: '/loadStream.io' }); - console.log("Currently Unavalible!"); } - } + }) } /** * @@ -176,4 +180,4 @@ class loadStream { resolve(res); }) } -} \ No newline at end of file +}