├── .babelrc
├── .editorconfig
├── .eslintrc
├── .gitignore
├── .npmignore
├── README.md
├── dist
├── vue-base64-file-upload.js
└── vue-base64-file-upload.min.js
├── example.gif
├── example
├── bundle.js
├── index.html
└── index.js
├── index.js
├── package.json
├── src
└── index.js
└── webpack.config.js
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | "es2015",
4 | "stage-0"
5 | ]
6 | }
7 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # http://editorconfig.org
2 | root = true
3 |
4 | [*]
5 | indent_style = space
6 | indent_size = 2
7 | end_of_line = lf
8 | charset = utf-8
9 | trim_trailing_whitespace = true
10 | insert_final_newline = true
11 |
12 | [*.md]
13 | trim_trailing_whitespace = false
14 |
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "parser": "babel-eslint",
3 |
4 | "extends": "eslint:recommended",
5 |
6 | env: {
7 | "browser": true,
8 | "mocha": true,
9 | "node": true,
10 | "es6": true
11 | },
12 |
13 | "parserOptions": {
14 | "ecmaFeatures": {
15 | "modules": true
16 | }
17 | },
18 |
19 | rules: {
20 | "strict": 0,
21 | "quotes": [2, "single"],
22 | "indent": [2, 2, {SwitchCase: 1}],
23 | "semi": [2, "always"],
24 | "no-underscore-dangle": 0,
25 | "no-unused-vars": 1,
26 | "no-unused-expressions": 0,
27 | "new-cap": 0,
28 | "no-extra-boolean-cast": 0,
29 | "yoda": 0,
30 | "no-empty": 0,
31 | "no-use-before-define": 0,
32 | "camelcase": 0,
33 | "object-curly-spacing": 0,
34 | "array-bracket-spacing": 0,
35 | "max-len": 0,
36 | "comma-dangle": [2, "never"],
37 | "space-before-function-paren": 0,
38 | "arrow-body-style": 0,
39 | "no-param-reassign": 0,
40 | "consistent-return": 0,
41 | "no-console": 0,
42 | "no-void": 0,
43 | "func-names": 0,
44 | "no-nested-ternary": 0,
45 | "quote-props": 0,
46 | "space-infix-ops": 0,
47 | "prefer-const": 0,
48 | "prefer-template": 0,
49 | "spaced-comment": 0,
50 | "prefer-rest-params": 0,
51 | "no-unreachable": 0
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | *.log
4 | *.map
5 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | example
2 | src
3 | .editorconfig
4 | .babelrc
5 | .eslintrc
6 | webpack.config.js
7 | example.gif
8 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # vue-base64-file-upload
2 |
3 | > Upload files as base64 data-uris (URL representing the file's data as a base64 encoded string).
4 |
5 |
6 |
7 | ## Install
8 |
9 | ```bash
10 | npm i vue-base64-file-upload --save
11 | ```
12 |
13 | ## Example
14 |
15 | ```js
16 | import Vue from 'vue';
17 | import VueBase64FileUpload from 'vue-base64-file-upload';
18 |
19 | const app = new Vue({
20 | components: {
21 | VueBase64FileUpload
22 | },
23 |
24 | data() {
25 | return {
26 | customImageMaxSize: 3 // megabytes
27 | };
28 | },
29 |
30 | methods: {
31 | onFile(file) {
32 | console.log(file); // file object
33 | },
34 |
35 | onLoad(dataUri) {
36 | console.log(dataUri); // data-uri string
37 | },
38 |
39 | onSizeExceeded(size) {
40 | alert(`Image ${size}Mb size exceeds limits of ${this.customImageMaxSize}Mb!`);
41 | }
42 | },
43 |
44 | template: `
45 |
46 |
Upload file
47 |
56 |
57 | `
58 | });
59 |
60 | app.$mount('#app');
61 | ```
62 |
63 | ## API
64 |
65 | ## Props
66 |
67 | - `image-class` - pass additional classes for preview `img` tag
68 | - `input-class` - pass additional classes for text `input` tag
69 | - `accept` - mimetypes allowed for upload, _defaults to `'image/png,image/gif,image/jpeg'`_
70 | - `max-size` - number of megabytes allowed for upload, _defaults to `10`_
71 | - `disable-preview` - not show preview image, _defaults to `false`_
72 | - `default-preview` - pass url or data-uri to be displayed as default image
73 | - `file-name` - pass custom filename to be displayed in text `input` tag
74 | - `placeholder` - pass placeholder text for text `input` tag
75 |
76 | ## Events
77 |
78 | - `file` - fired when file object is ready
79 | - `load` - fired when data-uri is ready
80 | - `size-exceeded` - fired if uploaded image size exceeds limits
81 |
82 | ## References
83 |
84 | - [FileReader API](https://developer.mozilla.org/en-US/docs/Web/API/FileReader)
85 | - [`readAsDataURL`](https://developer.mozilla.org/en-US/docs/Web/API/FileReader/readAsDataURL)
86 |
87 | ---
88 |
89 | **MIT Licensed**
90 |
--------------------------------------------------------------------------------
/dist/vue-base64-file-upload.js:
--------------------------------------------------------------------------------
1 | (function webpackUniversalModuleDefinition(root, factory) {
2 | if(typeof exports === 'object' && typeof module === 'object')
3 | module.exports = factory();
4 | else if(typeof define === 'function' && define.amd)
5 | define("VueBase64FileUpload", [], factory);
6 | else if(typeof exports === 'object')
7 | exports["VueBase64FileUpload"] = factory();
8 | else
9 | root["VueBase64FileUpload"] = factory();
10 | })(this, function() {
11 | return /******/ (function(modules) { // webpackBootstrap
12 | /******/ // The module cache
13 | /******/ var installedModules = {};
14 |
15 | /******/ // The require function
16 | /******/ function __webpack_require__(moduleId) {
17 |
18 | /******/ // Check if module is in cache
19 | /******/ if(installedModules[moduleId])
20 | /******/ return installedModules[moduleId].exports;
21 |
22 | /******/ // Create a new module (and put it into the cache)
23 | /******/ var module = installedModules[moduleId] = {
24 | /******/ exports: {},
25 | /******/ id: moduleId,
26 | /******/ loaded: false
27 | /******/ };
28 |
29 | /******/ // Execute the module function
30 | /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
31 |
32 | /******/ // Flag the module as loaded
33 | /******/ module.loaded = true;
34 |
35 | /******/ // Return the exports of the module
36 | /******/ return module.exports;
37 | /******/ }
38 |
39 |
40 | /******/ // expose the modules object (__webpack_modules__)
41 | /******/ __webpack_require__.m = modules;
42 |
43 | /******/ // expose the module cache
44 | /******/ __webpack_require__.c = installedModules;
45 |
46 | /******/ // __webpack_public_path__
47 | /******/ __webpack_require__.p = "";
48 |
49 | /******/ // Load entry module and return exports
50 | /******/ return __webpack_require__(0);
51 | /******/ })
52 | /************************************************************************/
53 | /******/ ([
54 | /* 0 */
55 | /***/ function(module, exports) {
56 |
57 | 'use strict';
58 |
59 | Object.defineProperty(exports, "__esModule", {
60 | value: true
61 | });
62 | if (!window.FileReader) {
63 | console.error('Your browser does not support FileReader API!');
64 | }
65 |
66 | exports.default = {
67 | name: 'vue-base64-file-upload',
68 |
69 | props: {
70 | imageClass: {
71 | type: String,
72 | default: ''
73 | },
74 | inputClass: {
75 | type: String,
76 | default: ''
77 | },
78 | accept: {
79 | type: String,
80 | default: 'image/png,image/gif,image/jpeg'
81 | },
82 | maxSize: {
83 | type: Number,
84 | default: 10 // megabytes
85 | },
86 | disablePreview: {
87 | type: Boolean,
88 | default: false
89 | },
90 | fileName: {
91 | type: String,
92 | default: ''
93 | },
94 | placeholder: {
95 | type: String,
96 | default: 'Click here to upload image'
97 | },
98 | defaultPreview: {
99 | type: String,
100 | default: ''
101 | }
102 | },
103 |
104 | data: function data() {
105 | return {
106 | file: null,
107 | preview: null,
108 | visiblePreview: false
109 | };
110 | },
111 |
112 |
113 | computed: {
114 | wrapperStyles: function wrapperStyles() {
115 | return {
116 | 'position': 'relative',
117 | 'width': '100%'
118 | };
119 | },
120 | fileInputStyles: function fileInputStyles() {
121 | return {
122 | 'width': '100%',
123 | 'position': 'absolute',
124 | 'top': 0,
125 | 'left': 0,
126 | 'right': 0,
127 | 'bottom': 0,
128 | 'opacity': 0,
129 | 'overflow': 'hidden',
130 | 'outline': 'none',
131 | 'cursor': 'pointer'
132 | };
133 | },
134 | textInputStyles: function textInputStyles() {
135 | return {
136 | 'width': '100%',
137 | 'cursor': 'pointer'
138 | };
139 | },
140 | previewImage: function previewImage() {
141 | return this.preview || this.defaultPreview;
142 | }
143 | },
144 |
145 | methods: {
146 | onChange: function onChange(e) {
147 | var _this = this;
148 |
149 | var files = e.target.files || e.dataTransfer.files;
150 |
151 | if (!files.length) {
152 | return;
153 | }
154 |
155 | var file = files[0];
156 | var size = file.size && file.size / Math.pow(1000, 2);
157 |
158 | // check file max size
159 | if (size > this.maxSize) {
160 | this.$emit('size-exceeded', size);
161 | return;
162 | }
163 |
164 | // update file
165 | this.file = file;
166 | this.$emit('file', file);
167 |
168 | var reader = new FileReader();
169 |
170 | reader.onload = function (e) {
171 | var dataURI = e.target.result;
172 |
173 | if (dataURI) {
174 | _this.$emit('load', dataURI);
175 |
176 | _this.preview = dataURI;
177 | }
178 | };
179 |
180 | // read blob url from file data
181 | reader.readAsDataURL(file);
182 | }
183 | },
184 |
185 | template: '\n \n '
186 | };
187 |
188 | /***/ }
189 | /******/ ])
190 | });
191 | ;
--------------------------------------------------------------------------------
/dist/vue-base64-file-upload.min.js:
--------------------------------------------------------------------------------
1 | !function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define("VueBase64FileUpload",[],t):"object"==typeof exports?exports.VueBase64FileUpload=t():e.VueBase64FileUpload=t()}(this,function(){return function(e){function t(n){if(i[n])return i[n].exports;var a=i[n]={exports:{},id:n,loaded:!1};return e[n].call(a.exports,a,a.exports,t),a.loaded=!0,a.exports}var i={};return t.m=e,t.c=i,t.p="",t(0)}([function(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),window.FileReader||console.error("Your browser does not support FileReader API!"),t.default={name:"vue-base64-file-upload",props:{imageClass:{type:String,default:""},inputClass:{type:String,default:""},accept:{type:String,default:"image/png,image/gif,image/jpeg"},maxSize:{type:Number,default:10},disablePreview:{type:Boolean,default:!1},fileName:{type:String,default:""},placeholder:{type:String,default:"Click here to upload image"},defaultPreview:{type:String,default:""}},data:function(){return{file:null,preview:null,visiblePreview:!1}},computed:{wrapperStyles:function(){return{position:"relative",width:"100%"}},fileInputStyles:function(){return{width:"100%",position:"absolute",top:0,left:0,right:0,bottom:0,opacity:0,overflow:"hidden",outline:"none",cursor:"pointer"}},textInputStyles:function(){return{width:"100%",cursor:"pointer"}},previewImage:function(){return this.preview||this.defaultPreview}},methods:{onChange:function(e){var t=this,i=e.target.files||e.dataTransfer.files;if(i.length){var n=i[0],a=n.size&&n.size/Math.pow(1e3,2);if(a>this.maxSize)return void this.$emit("size-exceeded",a);this.file=n,this.$emit("file",n);var r=new FileReader;r.onload=function(e){var i=e.target.result;i&&(t.$emit("load",i),t.preview=i)},r.readAsDataURL(n)}}},template:'\n \n '}}])});
--------------------------------------------------------------------------------
/example.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dhhb/vue-base64-file-upload/e2d57dcecf80181e26d2c4b57a7508f207895cbc/example.gif
--------------------------------------------------------------------------------
/example/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Vue Base64 File Upload Example
7 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/example/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue/dist/vue';
2 | import VueBase64FileUpload from '../dist/vue-base64-file-upload';
3 |
4 | const app = new Vue({
5 | components: {
6 | VueBase64FileUpload
7 | },
8 |
9 | data() {
10 | return {
11 | customImageMaxSize: 3 // megabytes
12 | };
13 | },
14 |
15 | methods: {
16 | onFile(file) {
17 | console.log(file);
18 | },
19 |
20 | onLoad(dataUri) {
21 | console.log('data-uri is ready!');
22 | },
23 |
24 | onSizeExceeded(size) {
25 | console.log(size);
26 | alert(`Image size exceeds limits of ${this.customImageMaxSize}Mb!`);
27 | }
28 | },
29 |
30 | template: `
31 |
32 |
Vue Base64 File Upload
33 |
34 |
43 |
44 |
45 |
51 |
52 |
53 | `
54 | });
55 |
56 | app.$mount('#app');
57 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 | if (!window.FileReader) {
7 | console.error('Your browser does not support FileReader API!');
8 | }
9 |
10 | exports.default = {
11 | name: 'vue-base64-file-upload',
12 |
13 | props: {
14 | imageClass: {
15 | type: String,
16 | default: ''
17 | },
18 | inputClass: {
19 | type: String,
20 | default: ''
21 | },
22 | accept: {
23 | type: String,
24 | default: 'image/png,image/gif,image/jpeg'
25 | },
26 | maxSize: {
27 | type: Number,
28 | default: 10 // megabytes
29 | },
30 | disablePreview: {
31 | type: Boolean,
32 | default: false
33 | },
34 | fileName: {
35 | type: String,
36 | default: ''
37 | },
38 | placeholder: {
39 | type: String,
40 | default: 'Click here to upload image'
41 | },
42 | defaultPreview: {
43 | type: String,
44 | default: ''
45 | }
46 | },
47 |
48 | data: function data() {
49 | return {
50 | file: null,
51 | preview: null,
52 | visiblePreview: false
53 | };
54 | },
55 |
56 |
57 | computed: {
58 | wrapperStyles: function wrapperStyles() {
59 | return {
60 | 'position': 'relative',
61 | 'width': '100%'
62 | };
63 | },
64 | fileInputStyles: function fileInputStyles() {
65 | return {
66 | 'width': '100%',
67 | 'position': 'absolute',
68 | 'top': 0,
69 | 'left': 0,
70 | 'right': 0,
71 | 'bottom': 0,
72 | 'opacity': 0,
73 | 'overflow': 'hidden',
74 | 'outline': 'none',
75 | 'cursor': 'pointer'
76 | };
77 | },
78 | textInputStyles: function textInputStyles() {
79 | return {
80 | 'width': '100%',
81 | 'cursor': 'pointer'
82 | };
83 | },
84 | previewImage: function previewImage() {
85 | return this.preview || this.defaultPreview;
86 | }
87 | },
88 |
89 | methods: {
90 | onChange: function onChange(e) {
91 | var _this = this;
92 |
93 | var files = e.target.files || e.dataTransfer.files;
94 |
95 | if (!files.length) {
96 | return;
97 | }
98 |
99 | var file = files[0];
100 | var size = file.size && file.size / Math.pow(1000, 2);
101 |
102 | // check file max size
103 | if (size > this.maxSize) {
104 | this.$emit('size-exceeded', size);
105 | return;
106 | }
107 |
108 | // update file
109 | this.file = file;
110 | this.$emit('file', file);
111 |
112 | var reader = new FileReader();
113 |
114 | reader.onload = function (e) {
115 | var dataURI = e.target.result;
116 |
117 | if (dataURI) {
118 | _this.$emit('load', dataURI);
119 |
120 | _this.preview = dataURI;
121 | }
122 | };
123 |
124 | // read blob url from file data
125 | reader.readAsDataURL(file);
126 | }
127 | },
128 |
129 | template: '\n \n '
130 | };
131 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vue-base64-file-upload",
3 | "version": "1.0.4",
4 | "description": "Upload files as base64 data-uris",
5 | "main": "./index.js",
6 | "directories": {
7 | "example": "example"
8 | },
9 | "scripts": {
10 | "build": "npm run build-babel && npm run build-dist-dev && npm run build-dist-prod",
11 | "build-dist-dev": "NODE_ENV=development webpack --config webpack.config --colors",
12 | "build-dist-prod": "NODE_ENV=production webpack --config webpack.config --progress --colors -p",
13 | "build-babel": "babel ./src/index.js --out-file ./index.js",
14 | "build-example": "browserify ./example/index.js -t [ babelify --presets [ es2015 stage-0 ] --plugins [ transform-object-assign ] ] -o ./example/bundle.js",
15 | "lint": "eslint ./src --fix",
16 | "test": "echo \"Comming soon ;)\" && exit 0"
17 | },
18 | "repository": {
19 | "type": "git",
20 | "url": "git+https://github.com/dhhb/vue-base64-file-upload.git"
21 | },
22 | "keywords": [
23 | "vue",
24 | "component",
25 | "upload",
26 | "input",
27 | "file",
28 | "base64",
29 | "data-uri",
30 | "blob"
31 | ],
32 | "author": "Dmitri Voronianski ",
33 | "license": "MIT",
34 | "bugs": {
35 | "url": "https://github.com/dhhb/vue-base64-file-upload/issues"
36 | },
37 | "homepage": "https://github.com/dhhb/vue-base64-file-upload#readme",
38 | "devDependencies": {
39 | "babel-cli": "^6.23.0",
40 | "babel-core": "^6.23.1",
41 | "babel-eslint": "^7.1.1",
42 | "babel-loader": "^6.3.2",
43 | "babel-plugin-add-module-exports": "^0.2.1",
44 | "babel-plugin-transform-object-assign": "^6.22.0",
45 | "babel-preset-es2015": "^6.22.0",
46 | "babel-preset-stage-0": "^6.22.0",
47 | "babelify": "^7.3.0",
48 | "browserify": "^14.1.0",
49 | "eslint": "^3.15.0",
50 | "webpack": "^1.14.0",
51 | "webpack-umd-external": "^1.0.2"
52 | },
53 | "dependencies": {
54 | "vue": "^2.1.10"
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | if (!window.FileReader) {
2 | console.error('Your browser does not support FileReader API!');
3 | }
4 |
5 | export default {
6 | name: 'vue-base64-file-upload',
7 |
8 | props: {
9 | imageClass: {
10 | type: String,
11 | default: ''
12 | },
13 | inputClass: {
14 | type: String,
15 | default: ''
16 | },
17 | accept: {
18 | type: String,
19 | default: 'image/png,image/gif,image/jpeg'
20 | },
21 | maxSize: {
22 | type: Number,
23 | default: 10 // megabytes
24 | },
25 | disablePreview: {
26 | type: Boolean,
27 | default: false
28 | },
29 | fileName: {
30 | type: String,
31 | default: ''
32 | },
33 | placeholder: {
34 | type: String,
35 | default: 'Click here to upload image'
36 | },
37 | defaultPreview: {
38 | type: String,
39 | default: ''
40 | }
41 | },
42 |
43 | data() {
44 | return {
45 | file: null,
46 | preview: null,
47 | visiblePreview: false
48 | };
49 | },
50 |
51 | computed: {
52 | wrapperStyles() {
53 | return {
54 | 'position': 'relative',
55 | 'width': '100%'
56 | };
57 | },
58 |
59 | fileInputStyles() {
60 | return {
61 | 'width': '100%',
62 | 'position': 'absolute',
63 | 'top': 0,
64 | 'left': 0,
65 | 'right': 0,
66 | 'bottom': 0,
67 | 'opacity': 0,
68 | 'overflow': 'hidden',
69 | 'outline': 'none',
70 | 'cursor': 'pointer'
71 | };
72 | },
73 |
74 | textInputStyles() {
75 | return {
76 | 'width': '100%',
77 | 'cursor': 'pointer'
78 | };
79 | },
80 |
81 | previewImage() {
82 | return this.preview || this.defaultPreview;
83 | }
84 | },
85 |
86 | methods: {
87 | onChange(e) {
88 | const files = e.target.files || e.dataTransfer.files;
89 |
90 | if (!files.length) {
91 | return;
92 | }
93 |
94 | const file = files[0];
95 | const size = file.size && (file.size / Math.pow(1000, 2));
96 |
97 | // check file max size
98 | if (size > this.maxSize) {
99 | this.$emit('size-exceeded', size);
100 | return;
101 | }
102 |
103 | // update file
104 | this.file = file;
105 | this.$emit('file', file);
106 |
107 | const reader = new FileReader();
108 |
109 | reader.onload = e => {
110 | const dataURI = e.target.result;
111 |
112 | if (dataURI) {
113 | this.$emit('load', dataURI);
114 |
115 | this.preview = dataURI;
116 | }
117 | };
118 |
119 | // read blob url from file data
120 | reader.readAsDataURL(file);
121 | }
122 | },
123 |
124 | template: `
125 |
145 | `
146 | };
147 |
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const env = process.env.NODE_ENV || 'development';
4 |
5 | const webpack = require('webpack');
6 | const path = require('path');
7 | const webpackUMDExternal = require('webpack-umd-external');
8 |
9 | const pluginsList = [];
10 | const outputFileName = env === 'production' ?
11 | 'vue-base64-file-upload.min.js' :
12 | 'vue-base64-file-upload.js';
13 |
14 | if (env === 'production') {
15 | pluginsList.push(
16 | new webpack.optimize.UglifyJsPlugin({
17 | compress: { warnings: false },
18 | output: { comments: false }
19 | })
20 | );
21 | }
22 |
23 | const config = {
24 | entry: path.join(__dirname, 'src/index.js'),
25 |
26 | output: {
27 | path: path.join(__dirname, 'dist'),
28 | filename: outputFileName,
29 | library: 'VueBase64FileUpload',
30 | libraryTarget: 'umd',
31 | umdNamedDefine: true
32 | },
33 |
34 | externals: webpackUMDExternal({
35 | 'vue': 'Vue'
36 | }),
37 |
38 | resolve: {
39 | extensions: ['', '.js'],
40 | alias: {
41 | vue: 'vue/dist/vue.js'
42 | }
43 | },
44 |
45 | plugins: pluginsList,
46 |
47 | module: {
48 | loaders: [{
49 | test: /\.jsx?$/,
50 | exclude: /node_modules/,
51 | loaders: ['babel']
52 | }]
53 | }
54 | };
55 |
56 | module.exports = config;
57 |
--------------------------------------------------------------------------------