@tahir-asadli/uploader 1.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +106 -0
- package/example.html +15 -0
- package/example.js +30 -0
- package/package.json +19 -0
- package/uploader.js +118 -0
package/README.md
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
## Introduction
|
|
2
|
+
|
|
3
|
+
A lightweight and efficient file uploading utility for modern web applications. This package provides an easy-to-use interface for handling file uploads, managing upload states, and integrating with your backend services.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
**Lightweight:** Zero or minimal dependencies to keep your bundle size small.<br/> **Customizable:** Flexible configuration for API endpoints, headers, and callbacks.
|
|
8
|
+
|
|
9
|
+
## Prerequisites
|
|
10
|
+
|
|
11
|
+
- Node.js 14+ (or compatible)
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
You can install the package via npm or yarn:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
# Using npm
|
|
19
|
+
npm install @tahir-asadli/uploader
|
|
20
|
+
|
|
21
|
+
# Using yarn
|
|
22
|
+
yarn add @tahir-asadli/uploader
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Quick Start
|
|
26
|
+
|
|
27
|
+
### Basic Usage
|
|
28
|
+
|
|
29
|
+
#### HTML
|
|
30
|
+
```html
|
|
31
|
+
<!DOCTYPE html>
|
|
32
|
+
<html lang="en">
|
|
33
|
+
<head>
|
|
34
|
+
<meta charset="UTF-8">
|
|
35
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
36
|
+
<meta name="csrf-token" content="csrf-token-value">
|
|
37
|
+
<title>Document</title>
|
|
38
|
+
</head>
|
|
39
|
+
<body>
|
|
40
|
+
<form action="/upload" enctype="multipart/form-data" method="post">
|
|
41
|
+
<input type="file" id="file" multiple="" name="file[]">
|
|
42
|
+
<input type="submit">
|
|
43
|
+
</form>
|
|
44
|
+
</body>
|
|
45
|
+
</html>
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
#### JavaScript
|
|
49
|
+
```js
|
|
50
|
+
import Uploader from '@tahir-asadli/uploader';
|
|
51
|
+
|
|
52
|
+
const requestHeaders = {};
|
|
53
|
+
|
|
54
|
+
let csrfTokenMeta = document.querySelector("meta[name=\"csrf-token\"]");
|
|
55
|
+
|
|
56
|
+
if (csrfTokenMeta != undefined) {
|
|
57
|
+
requestHeaders['X-CSRF-TOKEN'] = csrfTokenMeta.getAttribute("content");
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const mediaConfig = {
|
|
61
|
+
|
|
62
|
+
fileInputId: 'file',
|
|
63
|
+
url: '/upload',
|
|
64
|
+
headers: requestHeaders,
|
|
65
|
+
started: function (fileList) {
|
|
66
|
+
console.log('Upload started!');
|
|
67
|
+
},
|
|
68
|
+
progress: function (fileId, progress) {
|
|
69
|
+
console.log(`Uploading... ${progress}%`, fileId);
|
|
70
|
+
},
|
|
71
|
+
completed: function (fileId) {
|
|
72
|
+
console.log(`File uploaded! ${fileId}`);
|
|
73
|
+
},
|
|
74
|
+
error: function (fileId, error) {
|
|
75
|
+
console.error(`${error} ${fileId}`);
|
|
76
|
+
},
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
new Uploader(mediaConfig);
|
|
80
|
+
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## API Reference
|
|
84
|
+
|
|
85
|
+
`
|
|
86
|
+
new Uploader(options)
|
|
87
|
+
`
|
|
88
|
+
|
|
89
|
+
| Option | Type | Description |
|
|
90
|
+
|--------|------|-------------|
|
|
91
|
+
|`fileInputId`|`string`|HTML input ID|
|
|
92
|
+
|`endpoint`|`string`|The URL where files will be sent (Required).|
|
|
93
|
+
|`headers`|`object`|Custom HTTP headers (e.g., Auth tokens).|
|
|
94
|
+
|`started`|`function`|Callback function|
|
|
95
|
+
|`progress`|`function`|Callback function|
|
|
96
|
+
|`completed`|`function`|Callback function|
|
|
97
|
+
|`error`|`function`|Callback function|
|
|
98
|
+
|
|
99
|
+
## Contributing
|
|
100
|
+
|
|
101
|
+
Contributions and suggestions are welcome. Open an issue or submit a PR.
|
|
102
|
+
|
|
103
|
+
## License
|
|
104
|
+
|
|
105
|
+
MIT
|
|
106
|
+
|
package/example.html
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<meta name="csrf-token" content="csrf-token-value">
|
|
7
|
+
<title>Document</title>
|
|
8
|
+
</head>
|
|
9
|
+
<body>
|
|
10
|
+
<form action="/upload" enctype="multipart/form-data" method="post">
|
|
11
|
+
<input type="file" id="file" multiple="" name="file[]">
|
|
12
|
+
<input type="submit">
|
|
13
|
+
</form>
|
|
14
|
+
</body>
|
|
15
|
+
</html>
|
package/example.js
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import Uploader from '@tahir-asadli/uploader';
|
|
2
|
+
|
|
3
|
+
const requestHeaders = {};
|
|
4
|
+
|
|
5
|
+
let csrfTokenMeta = document.querySelector("meta[name=\"csrf-token\"]");
|
|
6
|
+
|
|
7
|
+
if (csrfTokenMeta != undefined) {
|
|
8
|
+
requestHeaders['X-CSRF-TOKEN'] = csrfTokenMeta.getAttribute("content");
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const mediaConfig = {
|
|
12
|
+
|
|
13
|
+
fileInputId: 'file',
|
|
14
|
+
url: '/upload',
|
|
15
|
+
headers: requestHeaders,
|
|
16
|
+
started: function (fileList) {
|
|
17
|
+
console.log('Upload started!');
|
|
18
|
+
},
|
|
19
|
+
progress: function (fileId, progress) {
|
|
20
|
+
console.log(`Uploading... ${progress}%`, fileId);
|
|
21
|
+
},
|
|
22
|
+
completed: function (fileId) {
|
|
23
|
+
console.log(`File uploaded! ${fileId}`);
|
|
24
|
+
},
|
|
25
|
+
error: function (fileId, error) {
|
|
26
|
+
console.error(`${error} ${fileId}`);
|
|
27
|
+
},
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
new Uploader(mediaConfig);
|
package/package.json
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@tahir-asadli/uploader",
|
|
3
|
+
"version": "1.0.10",
|
|
4
|
+
"description": "A lightweight and efficient file uploading utility for modern web applications. This package provides an easy-to-use interface for handling file uploads, managing upload states, and integrating with your backend services.",
|
|
5
|
+
"main": "uploader.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
8
|
+
},
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "git+https://github.com/tahir-asadli/uploader.git"
|
|
12
|
+
},
|
|
13
|
+
"author": "Tahir Asadli",
|
|
14
|
+
"license": "MIT",
|
|
15
|
+
"bugs": {
|
|
16
|
+
"url": "https://github.com/tahir-asadli/uploader/issues"
|
|
17
|
+
},
|
|
18
|
+
"homepage": "https://github.com/tahir-asadli/uploader#readme"
|
|
19
|
+
}
|
package/uploader.js
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
class Uploader {
|
|
2
|
+
|
|
3
|
+
constructor(options) {
|
|
4
|
+
|
|
5
|
+
this.fileInputId = options.fileInputId;
|
|
6
|
+
this.url = options.url;
|
|
7
|
+
this.headers = options.headers;
|
|
8
|
+
this.started = options.started;
|
|
9
|
+
this.progress = options.progress;
|
|
10
|
+
this.completed = options.completed;
|
|
11
|
+
this.error = options.error;
|
|
12
|
+
this.fileList = [];
|
|
13
|
+
this.uploading = false;
|
|
14
|
+
this.init();
|
|
15
|
+
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
init() {
|
|
19
|
+
|
|
20
|
+
this.addEvents();
|
|
21
|
+
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
addEvents() {
|
|
25
|
+
|
|
26
|
+
const fileInput = document.getElementById(this.fileInputId);
|
|
27
|
+
fileInput.addEventListener('change', (e) => {
|
|
28
|
+
this.generateList(e.target.files);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
generateList(files) {
|
|
34
|
+
|
|
35
|
+
Array.from(files).forEach((singleFile) => {
|
|
36
|
+
|
|
37
|
+
let fileId = this.uniqueId();
|
|
38
|
+
|
|
39
|
+
this.fileList.push({
|
|
40
|
+
id: fileId,
|
|
41
|
+
file: singleFile
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
this.started(this.fileList);
|
|
47
|
+
this.uploadFromList();
|
|
48
|
+
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
uploadFromList() {
|
|
52
|
+
|
|
53
|
+
if(this.fileList.length == 0 || this.uploading) {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
let ajax = new XMLHttpRequest();
|
|
58
|
+
let formData = new FormData();
|
|
59
|
+
let file = this.fileList[0];
|
|
60
|
+
|
|
61
|
+
formData.append("files[]", file.file);
|
|
62
|
+
|
|
63
|
+
ajax.upload.addEventListener("progress", (e) => {
|
|
64
|
+
|
|
65
|
+
let percent = Math.floor(e.loaded / e.total * 100);
|
|
66
|
+
this.uploading = true;
|
|
67
|
+
this.progress(file.id, percent);
|
|
68
|
+
|
|
69
|
+
}, false);
|
|
70
|
+
|
|
71
|
+
ajax.addEventListener("error", (e) => {
|
|
72
|
+
|
|
73
|
+
this.uploading = false;
|
|
74
|
+
this.fileList.shift();
|
|
75
|
+
this.uploadFromList();
|
|
76
|
+
this.error(file.id, 'Error occured!')
|
|
77
|
+
|
|
78
|
+
}, false);
|
|
79
|
+
|
|
80
|
+
ajax.addEventListener("abort", (e) => {
|
|
81
|
+
|
|
82
|
+
this.uploading = false;
|
|
83
|
+
this.error(file.id, 'Aborted!')
|
|
84
|
+
|
|
85
|
+
}, false);
|
|
86
|
+
|
|
87
|
+
ajax.addEventListener("load", (e) => {
|
|
88
|
+
|
|
89
|
+
this.uploading = false;
|
|
90
|
+
this.fileList.shift();
|
|
91
|
+
this.uploadFromList();
|
|
92
|
+
if(e.target.status == 200) {
|
|
93
|
+
this.completed(file.id, 'File uploaded!')
|
|
94
|
+
}else {
|
|
95
|
+
this.error(file.id, e.target.statusText)
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
}, false);
|
|
99
|
+
|
|
100
|
+
ajax.open("POST", this.url);
|
|
101
|
+
|
|
102
|
+
Object.keys(this.headers).forEach((key, i) => {
|
|
103
|
+
console.log(key, this.headers[key]);
|
|
104
|
+
ajax.setRequestHeader(key, this.headers[key]);
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
ajax.setRequestHeader("X-Requested-With", 'XMLHttpRequest');
|
|
108
|
+
ajax.send(formData);
|
|
109
|
+
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
uniqueId() {
|
|
113
|
+
return Math.random().toString(36).slice(2, 7);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export default Uploader;
|