1. front
HTML
main.ejs123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta name="description" content="How to create an image upload form without page refresh using Bootstrap, jQuery AJAX and PHP."><meta name="author" content="ShinDarth"><link rel="stylesheet" type="text/css" href="/css/style.css"><link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css"><link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap-theme.min.css"><style>body { padding-top:50px; }.navbar-inverse .navbar-nav > li > a { color: #DBE4E1; }</style><!--[if IE]><script src="https://cdn.jsdelivr.net/html5shiv/3.7.2/html5shiv.min.js"></script><script src="https://cdn.jsdelivr.net/respond/1.4.2/respond.min.js"></script><![endif]--></head><body><nav class="navbar navbar-inverse navbar-fixed-top" role="navigation"><div class="container"><div class="navbar-header"><button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse"><span class="sr-only">Toggle navigation</span><span class="icon-bar"></span><span class="icon-bar"></span><span class="icon-bar"></span></button><a class="navbar-brand" href="#"></a></div></div></nav><div class="container"><div class="containerStyle"><div class="panel panel-primary"><div class="panel-heading"><h2>Google image analysis</h2></div><div class="panel-body"><p class="lead">Select a PNG or JPEG image, having maximum size <span id="max-size"></span> KB.</p><div id="image-preview-div" style="display: none"><label for="exampleInputFile">Selected image:</label><br><img id="preview-img" src="noimage"></div><div class="form-group"><input type="file" name="file" id="file" required></div><div class="text-center"><button type="button" class="btn btn-primary" id="upload-image-button" disabled><i class="glyphicon glyphicon-film">Image analyze</i></button><button type="button" class="btn btn-primary" id="upload-text-button" disabled><i class="glyphicon glyphicon-file">Text analyze</i></button></div><br><div class="alert alert-info" id="loading" style="display: none;" role="alert">Uploading image...<div class="progress"><div id="progress-bar" class="progress-bar progress-bar-striped active" role="progressbar" aria-valuenow="45" aria-valuemin="0" aria-valuemax="100"></div></div></div></div></div></div><br><br><div id="result" class="containerStyle"><div class="panel panel-primary"><div class="panel-heading"><h2>Analyzed result</h2></div><div class="panel-body"><h3>Analyzed result for user</h3><div class="panel panel-default" id="message-for-user"></div><h3>Analyzed result for developer</h3><button type="button" class="btn btn-info" data-toggle="collapse" data-target="#message-for-developer">show or hide</button><div id="message-for-developer" class="collapse panel panel-default"></div></div></div></div></div><script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script><script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js"></script><script src="/js/upload-image.js"></script></body></html>cs - JAVASCRIPT
upload-file.js - 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120/*jslint browser: true, white: true, eqeq: true, plusplus: true, sloppy: true, vars: true*//*global $, console, alert, FormData, FileReader*/function noPreview() {$('#image-preview-div').css("display", "none");$('#preview-img').attr('src', 'noimage');$('upload-button').attr('disabled', '');}function selectImage(e) {$('#file').css("color", "green");$('#image-preview-div').css("display", "block");$('#preview-img').attr('src', e.target.result);$('#preview-img').css('max-width', '550px');}$(document).ready(function (e) {//set up maxsizevar maxsize = 500 * 1024; // 500 KB$('#max-size').html((maxsize/1024).toFixed(2));$('#result').hide();$('#upload-text-button').click(function(){var formData = new FormData();var files = $('#file')[0].files[0];formData.append('file', files);$('#result').hide();$('#message-for-user').empty();$('#message-for-developer').empty();$('#loading').show();$.ajax({url: "/text",type: "POST",data: formData,contentType: false,cache: false,processData: false,success: function(data){$('#loading').hide();$('#message-for-user').append(`Description:${data[0]['description']}`);$('#message-for-developer').append(JSON.stringify(data));$('#result').show();}});});$('#upload-image-button').click(function(){var formData = new FormData();var files = $('#file')[0].files[0];formData.append('file', files);$('#result').hide();$('#message-for-user').empty();$('#message-for-developer').empty();$('#loading').show();$.ajax({url: "/image",type: "POST",data: formData,contentType: false,cache: false,processData: false,success: function(data){$('#loading').hide();$('#message-for-user').append(`Description:${data[0]['description']}`);$('#message-for-developer').append(JSON.stringify(data));$('#result').show();}});});//$('#file').change(function() {$('#message').empty();var file = this.files[0];var match = ["image/jpeg", "image/png", "image/jpg"];if ( !( (file.type == match[0]) || (file.type == match[1]) || (file.type == match[2]) ) ){noPreview();$('#message').html('<div class="alert alert-warning" role="alert">Unvalid image format. Allowed formats: JPG, JPEG, PNG.</div>');return false;}if ( file.size > maxsize ){noPreview();$('#message').html('<div class=\"alert alert-danger\" role=\"alert\">The size of image you are attempting to upload is ' + (file.size/1024).toFixed(2) + ' KB, maximum size allowed is ' + (maxsize/1024).toFixed(2) + ' KB</div>');return false;}$('#upload-image-button').removeAttr("disabled");$('#upload-text-button').removeAttr("disabled");var reader = new FileReader();reader.onload = selectImage;reader.readAsDataURL(this.files[0]);});});
cs
➡
1. var files = $('#file')[0].files[0];하면, HTML 쪽에서 <input type="file" name="file" id="file" required로 업로드했던 파일이 files변수에 담기게 된다.
2. var formData = new FormData();로 생성한 formData 객체에 formData.append('file', files);로 append하면, formData변수에 파일이 담긴다. 이걸로 서버로 전송할 준비가 완료.
3. ajax에 담아서 송신 - CSS12345678.containerStyle{max-width: 650px;margin: auto;}#progress-bar{width: 100%;}
cs
2. Server
app.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | 'use strict'; global.__base = __dirname + "/src"; //require external modules const bodyParser = require('body-parser'); const co = require('co'); const VisionExt = require(__base + '/google/vision_ext') const formidable = require(__base + '/upload-file/formidable-send'); //Declare express and configurate const express = require('express'); const app = express(); //Configure Directory path app.use(bodyParser.urlencoded({extended : false})); app.use(express.static('./public')); app.set('view engine','ejs'); app.set('views', './views'); app.post('/image', function (req,res){ const uploadedDir=__dirname + "/public/image"; co(function*(){ const tgFile = yield formidable.uploadFile(req,uploadedDir); const result = yield VisionExt.labelDetection(tgFile); yield res.send(result); }) }); app.post('/text', function (req,res){ const uploadedDir=__dirname + "/public/image"; co(function*(){ const tgFile = yield formidable.uploadFile(req,uploadedDir); const result = yield VisionExt.textDetection(tgFile); yield res.send(result); }) }); app.get('/', function(req,res){ res.render('main2'); }); app.listen(5100,'127.0.0.1', function() { console.log('connection complete. Open page localhost:5100'); }); | cs |
➡
formidable 모듈로 ajax로 송신된 파일을 담음. 이때, req에는 송신된 file이 보이지 않지만 formidable로는 보이므로 req에서 보이지 않아도 크게 염려하지 말것.
formidable-send.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | 'use strict'; const formidable = require('formidable'); const fs = require('fs'); exports.uploadFile=function(req,dir){ return new Promise(function(resolve){ const form = new formidable.IncomingForm(), files = [], fields = []; form.parse(req); form.uploadDir = dir; let tgFile; form .on('field', function(field, value) { console.log(field, value); fields.push([field, value]); }) .on('file', function(field, file) { console.log(field, file); fs.renameSync(file.path, form.uploadDir + "/" + file.name); tgFile = form.uploadDir + "/" + file.name; files.push([field, file]); }) .on('end', function() { console.log('-> upload done'); resolve(tgFile); }); }); } | cs |
vision-ext.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | 'use strict'; // Imports the Google Cloud client library const vision = require('@google-cloud/vision'); // Creates a client const client = new vision.ImageAnnotatorClient({ keyFilename:__base+'/config/GAC.json' }); exports.labelDetection=function(filePath){ return new Promise(function(resolve){ client .labelDetection(filePath) .then(results => { const detections = results[0].labelAnnotations; resolve(detections); }) .catch(err => { console.error('ERROR:', err); }); }); } exports.textDetection=function(filePath){ return new Promise(function(resolve){ client .textDetection(filePath) .then(results => { const detections = results[0].textAnnotations; resolve(detections); }) .catch(err => { console.error('ERROR:', err); }); }); } | cs |
'C Lang > JS Technic' 카테고리의 다른 글
socket.io 모듈:socket.emit과 socket.on (0) | 2018.08.06 |
---|---|
실시간 데이터 송신의 진화 : 폴링 방식, 롱폴링 방식, 웹소켓 (1) | 2018.08.06 |
pm2 설정파일을 통한 환경변수로 pm2 start (0) | 2018.07.25 |
Object.assign, 복사 대상과 참조가 연결되는 얕은 복사(shallow copy), 아예 새로운 객체를 복사하는 깊은 복사(deep copy) (0) | 2018.07.24 |
array.reduce 함수 (0) | 2018.07.24 |