├── README.md ├── aa.gif ├── icons ├── doc.png ├── mp3.png ├── mp4.png ├── pdf.png ├── png.png ├── txt.png └── zip.png ├── index.css ├── index.css.map ├── index.js ├── index.php ├── index.scss ├── upload.php └── upload └── .DS_Store /README.md: -------------------------------------------------------------------------------- 1 | # js-progress-bar-multi-upload 2 | Multi Upload with Progress Bar in Vanilla JS 3 | 4 | Youtube dersinde birlikte hazırladığımız çoklu progress barlı javascript uploader örneği. 5 | 6 | ![aa.gif](aa.gif) 7 | -------------------------------------------------------------------------------- /aa.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tayfunerbilen/js-progress-bar-multi-upload/2563f059b3de82858cb0c595c08fabc983e894d9/aa.gif -------------------------------------------------------------------------------- /icons/doc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tayfunerbilen/js-progress-bar-multi-upload/2563f059b3de82858cb0c595c08fabc983e894d9/icons/doc.png -------------------------------------------------------------------------------- /icons/mp3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tayfunerbilen/js-progress-bar-multi-upload/2563f059b3de82858cb0c595c08fabc983e894d9/icons/mp3.png -------------------------------------------------------------------------------- /icons/mp4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tayfunerbilen/js-progress-bar-multi-upload/2563f059b3de82858cb0c595c08fabc983e894d9/icons/mp4.png -------------------------------------------------------------------------------- /icons/pdf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tayfunerbilen/js-progress-bar-multi-upload/2563f059b3de82858cb0c595c08fabc983e894d9/icons/pdf.png -------------------------------------------------------------------------------- /icons/png.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tayfunerbilen/js-progress-bar-multi-upload/2563f059b3de82858cb0c595c08fabc983e894d9/icons/png.png -------------------------------------------------------------------------------- /icons/txt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tayfunerbilen/js-progress-bar-multi-upload/2563f059b3de82858cb0c595c08fabc983e894d9/icons/txt.png -------------------------------------------------------------------------------- /icons/zip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tayfunerbilen/js-progress-bar-multi-upload/2563f059b3de82858cb0c595c08fabc983e894d9/icons/zip.png -------------------------------------------------------------------------------- /index.css: -------------------------------------------------------------------------------- 1 | *{padding:0;margin:0;list-style:none;border:0;box-sizing:border-box;outline:0;font-family:"Segoe UI",Tahoma,Geneva,Verdana,sans-serif}body{background:#eee}.dropzone{width:500px;margin:20px auto;background:#fff;border:1px solid #ddd}.dropzone .dropzone-form{height:150px;display:flex;align-items:center;justify-content:center;position:relative}.dropzone .dropzone-form.active{background-color:rgba(0,128,0,.15)}.dropzone .dropzone-form.active p{color:green}.dropzone .dropzone-form input{position:absolute;top:0;left:0;width:100%;height:100%;opacity:0;cursor:pointer}.dropzone .dropzone-form p{font-size:15px;color:#999}.dropzone .dropzone-result-text{border-top:1px solid #ddd;padding:15px;text-align:center;font-size:14px;background:rgba(0,98,255,.149);color:#0062ff}.dropzone .dropzone-result-text:empty{display:none}.dropzone .dropzone-result-text.success{background:rgba(0,128,0,.149);color:green}.dropzone .dropzone-result{border-top:1px solid #ddd}.dropzone .dropzone-result:empty{display:none}.dropzone .dropzone-result .file{display:flex;align-items:center;padding:15px 15px 15px 0}.dropzone .dropzone-result .file:not(:last-child){border-bottom:1px solid #eee}.dropzone .dropzone-result .file .icon{width:50px;text-align:center}.dropzone .dropzone-result .file .icon img{max-width:60%}.dropzone .dropzone-result .file .file-inner{flex:1}.dropzone .dropzone-result .file .file-inner .title{font-size:14px;color:#444}.dropzone .dropzone-result .file .file-inner .bar{height:6px;border-radius:6px;background:#ddd;margin-top:7px}.dropzone .dropzone-result .file .file-inner .bar span{height:6px;display:block;border-radius:6px;background:#639}.dropzone .dropzone-result .file .file-inner .error-text{font-size:12px;color:red;padding-top:3px;display:none}.dropzone .dropzone-result .file .file-inner .abort-btn{margin-top:7px;background:transparent;cursor:pointer;color:darkred;text-decoration:underline;font-size:12px}.dropzone .dropzone-result .file.error{background-color:rgba(255,0,0,.162)}.dropzone .dropzone-result .file.error .file-inner .error-text{display:block}.dropzone .dropzone-result .file.success .file-inner .abort-btn,.dropzone .dropzone-result .file.error .file-inner .abort-btn,.dropzone .dropzone-result .file.current .file-inner .abort-btn,.dropzone .dropzone-result .file.aborted .file-inner .abort-btn{display:none}.dropzone .dropzone-result .file.aborted{background-color:rgba(255,166,0,.135)}/*# sourceMappingURL=index.css.map */ 2 | -------------------------------------------------------------------------------- /index.css.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sourceRoot":"","sources":["index.scss"],"names":[],"mappings":"AAAA,EACI,UACA,SACA,gBACA,SACA,sBACA,UACA,wDAGJ,KACI,gBAGJ,UACI,YACA,iBACA,gBACA,sBACA,yBACI,aACA,aACA,mBACA,uBACA,kBACA,gCACI,mCACA,kCACI,YAGR,+BACI,kBACA,MACA,OACA,WACA,YACA,UACA,eAEJ,2BACI,eACA,WAGR,gCACI,0BACA,aACA,kBACA,eACA,+BACA,cACA,sCACI,aAEJ,wCACI,8BACA,YAGR,2BACI,0BACA,iCACI,aAEJ,iCACI,aACA,mBACA,yBACA,kDACI,6BAEJ,uCACI,WACA,kBACA,2CACI,cAGR,6CACI,OACA,oDACI,eACA,WAEJ,kDACI,WACA,kBACA,gBACA,eACA,uDACI,WACA,cACA,kBACA,gBAGR,yDACI,eACA,UACA,gBACA,aAEJ,wDACI,eACA,uBACA,eACA,cACA,0BACA,eAGR,uCACI,oCACA,+DACI,cAIJ,8PACI,aAGR,yCACI","file":"index.css"} -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | function fileIcon(name) { 2 | if (name.match(/\.jpe?g|png|gif|webp/)) { 3 | return 'png' 4 | } 5 | else if (name.match(/\.zip|rar/)) { 6 | return 'zip' 7 | } 8 | else if (name.match(/\.mp4/)) { 9 | return 'mp4' 10 | } 11 | else if (name.match(/\.mp3/)) { 12 | return 'mp3' 13 | } 14 | else if (name.match(/\.pdf/)) { 15 | return 'pdf' 16 | } 17 | else if (name.match(/\.txt/)) { 18 | return 'txt' 19 | } 20 | return 'doc' 21 | } 22 | 23 | function fileUpload(index) { 24 | const {file, el} = files[index] 25 | 26 | if (file.size > MAX_UPLOAD_SIZE) { 27 | el.classList.add('error'); 28 | el.querySelector('.error-text').innerText = 'Yüklenen dosya büyüklüğü fazla geldi hacı!'; 29 | 30 | if (index + 1 < files.length) { 31 | fileUpload(index + 1) 32 | } else { 33 | resultText.innerText = `Dosyalar başarıyla yüklendi` 34 | resultText.classList.add('success') 35 | } 36 | 37 | } else { 38 | 39 | const formData = new FormData() 40 | formData.append('file', file) 41 | 42 | el.classList.add('current') 43 | resultText.classList.remove('success') 44 | resultText.innerText = `Dosyalar yükleniyor.. (${index + 1}/${files.length})` 45 | 46 | const request = new XMLHttpRequest() 47 | 48 | request.addEventListener('error', function() { 49 | el.classList.add('error'); 50 | el.querySelector('.error-text').innerText = 'Dosya yükleme işlemi iptal edildi.'; 51 | }); 52 | 53 | request.addEventListener('load', function() { 54 | const response = JSON.parse(this.response); 55 | if (response.error) { 56 | el.classList.add('error'); 57 | el.querySelector('.error-text').innerText = response.msg; 58 | } 59 | 60 | if (response.success) { 61 | el.classList.remove('current') 62 | el.classList.add('success') 63 | } 64 | 65 | if (index + 1 < files.length) { 66 | fileUpload(index + 1) 67 | } else { 68 | // yükleme işlemi bitmiş 69 | resultText.innerText = `Dosyalar başarıyla yüklendi` 70 | resultText.classList.add('success') 71 | } 72 | }) 73 | 74 | request.upload.addEventListener('progress', function(e) { 75 | let percent = (e.loaded / e.total) * 100; 76 | el.querySelector('.bar span').style.width = percent + '%'; 77 | }) 78 | 79 | request.open('POST', 'upload.php'); 80 | request.send(formData) 81 | 82 | } 83 | 84 | } 85 | 86 | function abortUpload(btn) { 87 | const parent = btn.closest('.file') 88 | parent.classList.add('aborted'); 89 | files = files.filter(({file, el}) => el !== parent) 90 | } 91 | 92 | const fileInput = document.querySelector('.dropzone-form input'), 93 | dropzoneForm = document.querySelector('.dropzone-form'), 94 | result = document.querySelector('.dropzone-result'), 95 | resultText = document.querySelector('.dropzone-result-text'); 96 | 97 | let files = []; 98 | 99 | dropzoneForm.addEventListener('dragenter', () => dropzoneForm.classList.add('active')); 100 | ['dragleave', 'drop'].forEach(method => { 101 | dropzoneForm.addEventListener(method, () => dropzoneForm.classList.remove('active')) 102 | }) 103 | 104 | fileInput.addEventListener('change', function() { 105 | files = []; 106 | [...this.files].map(file => { 107 | const item = document.createElement('div'); 108 | item.className = 'file'; 109 | item.innerHTML = `
110 | 111 |
112 |
113 |
${file.name}
114 |
115 | 116 |
117 |
118 | 119 |
` 120 | result.appendChild(item); 121 | files.push({ 122 | file, 123 | el: item 124 | }) 125 | }) 126 | fileUpload(0) 127 | }) -------------------------------------------------------------------------------- /index.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Javascript ile Progress Barlı Upload İşlemi 6 | 7 | 10 | 11 | 12 | 13 |
14 |
15 | 16 |

Dosyalarınızı buraya sürükleyin ya da seçmek için tıklayın!

17 |
18 |
19 |
20 |
21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /index.scss: -------------------------------------------------------------------------------- 1 | * { 2 | padding: 0; 3 | margin: 0; 4 | list-style: none; 5 | border: 0; 6 | box-sizing: border-box; 7 | outline: 0; 8 | font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; 9 | } 10 | 11 | body { 12 | background: #eee; 13 | } 14 | 15 | .dropzone { 16 | width: 500px; 17 | margin: 20px auto; 18 | background: #fff; 19 | border: 1px solid #ddd; 20 | .dropzone-form { 21 | height: 150px; 22 | display: flex; 23 | align-items: center; 24 | justify-content: center; 25 | position: relative; 26 | &.active { 27 | background-color: rgba(0, 128, 0, 0.15); 28 | p { 29 | color: green; 30 | } 31 | } 32 | input { 33 | position: absolute; 34 | top: 0; 35 | left: 0; 36 | width: 100%; 37 | height: 100%; 38 | opacity: 0; 39 | cursor: pointer; 40 | } 41 | p { 42 | font-size: 15px; 43 | color: #999; 44 | } 45 | } 46 | .dropzone-result-text { 47 | border-top: 1px solid #ddd; 48 | padding: 15px; 49 | text-align: center; 50 | font-size: 14px; 51 | background: rgba(0, 98, 255, 0.149); 52 | color: rgba(0, 98, 255, 1); 53 | &:empty { 54 | display: none; 55 | } 56 | &.success { 57 | background: rgba(0, 128, 0, 0.149); 58 | color: green; 59 | } 60 | } 61 | .dropzone-result { 62 | border-top: 1px solid #ddd; 63 | &:empty { 64 | display: none; 65 | } 66 | .file { 67 | display: flex; 68 | align-items: center; 69 | padding: 15px 15px 15px 0; 70 | &:not(:last-child) { 71 | border-bottom: 1px solid #eee; 72 | } 73 | .icon { 74 | width: 50px; 75 | text-align: center; 76 | img { 77 | max-width: 60%; 78 | } 79 | } 80 | .file-inner { 81 | flex: 1; 82 | .title { 83 | font-size: 14px; 84 | color: #444; 85 | } 86 | .bar { 87 | height: 6px; 88 | border-radius: 6px; 89 | background: #ddd; 90 | margin-top: 7px; 91 | span { 92 | height: 6px; 93 | display: block; 94 | border-radius: 6px; 95 | background: rebeccapurple 96 | } 97 | } 98 | .error-text { 99 | font-size: 12px; 100 | color: red; 101 | padding-top: 3px; 102 | display: none; 103 | } 104 | .abort-btn { 105 | margin-top: 7px; 106 | background: transparent; 107 | cursor: pointer; 108 | color: darkred; 109 | text-decoration: underline; 110 | font-size: 12px; 111 | } 112 | } 113 | &.error { 114 | background-color: rgba(255, 0, 0, 0.162); 115 | .file-inner .error-text { 116 | display: block 117 | } 118 | } 119 | &.success, &.error, &.current, &.aborted { 120 | .file-inner .abort-btn { 121 | display: none; 122 | } 123 | } 124 | &.aborted { 125 | background-color: rgba(255, 166, 0, 0.135); 126 | } 127 | } 128 | } 129 | } -------------------------------------------------------------------------------- /upload.php: -------------------------------------------------------------------------------- 1 | true, 6 | 'msg' => 'Zip dosyası yükleyemezsiniz!' 7 | ]); 8 | return; 9 | } 10 | 11 | $tmp = $_FILES['file']['tmp_name']; 12 | $path = basename($_FILES['file']['name']); 13 | move_uploaded_file($tmp, "upload/{$path}"); 14 | 15 | echo json_encode([ 16 | 'success' => true, 17 | 'msg' => 'Dosya başarıyla yüklendi', 18 | 'path' => "upload/{$path}", 19 | 'file' => $_FILES['file']['name'] 20 | ]); -------------------------------------------------------------------------------- /upload/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tayfunerbilen/js-progress-bar-multi-upload/2563f059b3de82858cb0c595c08fabc983e894d9/upload/.DS_Store --------------------------------------------------------------------------------