├── CHANGELOG.md ├── logos ├── logo-box-builtby.png └── logo-box-madefor.png ├── package.json ├── test.html ├── index.js └── README.md /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## 1.0.0 (2023-07-05) 4 | 5 | Initial release. 6 | -------------------------------------------------------------------------------- /logos/logo-box-builtby.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apostrophecms/scale/main/logos/logo-box-builtby.png -------------------------------------------------------------------------------- /logos/logo-box-madefor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apostrophecms/scale/main/logos/logo-box-madefor.png -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@apostrophecms/scale", 3 | "version": "1.0.0", 4 | "description": "Scale an image file in the browser before uploading it to your server", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/apostrophecms/scale.git" 12 | }, 13 | "keywords": [ 14 | "scale", 15 | "image", 16 | "image", 17 | "scale" 18 | ], 19 | "type": "module", 20 | "author": "Apostrophe Technologies", 21 | "license": "MIT", 22 | "bugs": { 23 | "url": "https://github.com/apostrophecms/scale/issues" 24 | }, 25 | "homepage": "https://github.com/apostrophecms/scale#readme" 26 | } 27 | -------------------------------------------------------------------------------- /test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 |
7 |
4 |
5 | ## Purpose
6 |
7 | Resizing 16-megapixel images on the server side can easily DOS your server
8 | (Denial Of Service). This module scales images appropriately in the browser
9 | before uploading them to your server.
10 |
11 | ## Installation
12 |
13 | ```bash
14 | npm install @apostrophecms/scale
15 | ```
16 |
17 | ## Usage
18 |
19 | ```javascript
20 | import scale from '@apostrophecms/scale';
21 |
22 | // See test.html for sample markup
23 | const input = document.querySelector('#file-input');
24 | input.addEventListener('change', async e => {
25 | let file = input.files[0];
26 |
27 | // Limit the maximum size
28 | file = await scale(file, {
29 | maxWidth: 1600,
30 | maxHeight: 1600
31 | });
32 |
33 | // Upload as multipart/form-data just like always
34 | const body = new FormData();
35 | body.append('file', file);
36 | const response = await fetch('/upload', {
37 | method: 'POST',
38 | body
39 | });
40 | });
41 | ```
42 |
43 | **The aspect ratio always stays the same.** There is no cropping, letterboxing or stretching. All we care about here is reducing file size by reducing overall dimensions.
44 |
45 | By default, the content type stays the same (`image/jpeg` stays JPEG, `image/png` stays PNG, etc).
46 |
47 | That's it! You're good to go.
48 |
49 | ## Fancy options
50 |
51 | ### Changing the file's content type
52 |
53 | If you want, you can turn everything into a WebP file (depending on browser support, you may get PNG as a fallback):
54 |
55 | ```javascript
56 | file = await scale(file, {
57 | maxWidth: 1600,
58 | maxHeight: 1600,
59 | type: 'image/webp'
60 | });
61 | ```
62 |
63 | Or, specify a mapping from type names to new type names:
64 |
65 | ```javascript
66 | file = await scale(file, {
67 | maxWidth: 1600,
68 | maxHeight: 1600,
69 | type: {
70 | 'image/gif': 'image/png',
71 | 'image/webp': 'image/png',
72 | 'image/png': 'image/png',
73 | 'image/jpeg': 'image/jpeg',
74 | }
75 | });
76 | ```
77 |
78 | Or, pass your own function:
79 |
80 | ```javascript
81 | file = await scale(file, {
82 | maxWidth: 1600,
83 | maxHeight: 1600,
84 | type(name) => (name === 'image/gif') ? 'image/png' : name
85 | });
86 | ```
87 |
88 | ### Falling back to the original file
89 |
90 | If you want, you can let the browser pass the original file in cases where scaling somehow fails:
91 |
92 | ```javascript
93 | file = await scale(file, {
94 | maxWidth: 1600,
95 | maxHeight: 1600,
96 | fallback: true
97 | });
98 | ```
99 |
100 | Otherwise an error is thrown in this situation.
101 |
102 | ## Previewing the image
103 |
104 | ```javascript
105 | file = await scale(file, {
106 | maxWidth: 1600,
107 | maxHeight: 1600
108 | });
109 |
110 | const img = document.querySelector('#my-img-element');
111 | img.setAttribute('src', URL.createObjectURL(file));
112 | ```
113 |
114 | `URL.createObjectURL` can turn the returned object into a suitable URL for use with `img src` or `style: background-image`.
115 |
116 | ## "What about the server side?"
117 |
118 | That depends entirely on your language and framework of choice. If you're using
119 | Node.js, check out [multiparty](https://www.npmjs.com/package/multiparty) and
120 | [sharp](https://sharp.pixelplumbing.com/). Remember, you can never trust the
121 | browser, so using a library like `sharp` to validate the images is still
122 | important.
123 |
--------------------------------------------------------------------------------