-
Notifications
You must be signed in to change notification settings - Fork 0
/
app.js
169 lines (144 loc) · 5.12 KB
/
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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
'use strict';
var express = require('express');
var app = express();
var cfenv = require("cfenv");
var http = require("http").Server(app);
var request = require("request");
// bodyParser is middleware that creates a new body object containing key-value pairs,
// where the value can be a string or array (when extended is false), or any type (when extended is true)
var bodyParser = require('body-parser');
var multer = require('multer');
var fs = require('fs');
var path = require('path');
var mime = require('mime');
const VisualRecognitionV3 = require('ibm-watson/visual-recognition/v3');
const { IamAuthenticator } = require('ibm-watson/auth');
const crypto = require('crypto');
const IMAGE_SIZE_LIMIT_BYTES = 2000000; //2MB
const UPLOAD_DIR_NAME = "uploads";
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, './uploads/')
},
filename: function (req, file, cb) {
crypto.pseudoRandomBytes(16, function (err, raw) {
cb(null, raw.toString('hex') + Date.now() + '.' + mime.extension(file.mimetype));
});
}
});
var upload = multer({ storage: storage });
app.use(bodyParser.urlencoded({ extended: true }));
// use the cfenv package to grab our application environment obj
var appEnv = cfenv.getAppEnv();
// get the bounded IBM Cloud service credentials
var watsonService = appEnv.getService("Hotdog-Visual-Recognition");
var apikey = watsonService.credentials.api_key;
// serviceUrl may be incorrect, it might be a different key under vcap services.
var serviceUrl = watsonService.credentials.serviceUrl;
const visualRecognition = new VisualRecognitionV3({
serviceUrl,
version: '2018-03-19',
authenticator: new IamAuthenticator({ apikey }),
});
// Configure views
app.use(express.static(path.join(__dirname, 'views')));
//make uploads dir if it doesn't exist
if (!fs.existsSync(UPLOAD_DIR_NAME)){
fs.mkdirSync(UPLOAD_DIR_NAME);
}
// Handle HTTP GET request to the "/" URL
app.get('/', function(req, res) {
res.render('index');
});
app.post('/hotdog', upload.single('maybe-hotdog-image'), function(req, res) {
// make sure there is an image to process
if(typeof req.file === "undefined"){
return res.status(400).json({msg: "An image must be provided"});
}
var filePath = req.file.path;
// check its only png or jpeg (watson service only uses those 2 mimetypes)
var mtype = req.file.mimetype;
if(typeof mtype === "undefined" || (mtype !== "image/jpeg" && mtype !== "image/png")){
deleteFile(filePath);
return res.status(400).json({msg: "Only jpeg and png images are allowed"});
}
// limit size to 2MB
if(req.file.size > IMAGE_SIZE_LIMIT_BYTES){
deleteFile(filePath);
return res.status(400).json({msg: "Images must be 2MB or less. Your image was: " + formatBytes(req.file.size)});
}
var params = {
classifierIds: ["Hotdogs_1346435223"],
threshold: .5,
imagesFile: fs.createReadStream(filePath)
};
visualRecognition.classify(params)
.then(response => {
// now that the image is classified we can delete it from uploads folder
deleteFile(filePath);
return res.status(200).json(response.result);
})
.catch(err => {
console.log(err);
return res.status(500).json({msg: "Failure to classify image: " + err});
});
});
app.get('/hotdog', upload.single('maybe-hotdog-image'), function(req, res) {
var url = req.query.url;
// make sure there is an image to process
if(typeof url === "undefined" || url === ""){
return res.status(400).json({msg: "A url must be provided"});
}
// poke the provided url to validate the image before sending to watson
getURLHeaders(url, function(err, headers){
if(err){
return res.status(502).json({msg: "Failure to verify image"});
}
var contentType = headers['content-type'];
var contentLength = headers['content-length'];
if(typeof contentType === "undefined" || (contentType !== "image/jpeg" && contentType !== "image/png")){
return res.status(400).json({msg: "Only jpeg and png images are allowed"});
}
// limit size to 2MB
if(contentLength > IMAGE_SIZE_LIMIT_BYTES){
return res.status(400).json({msg: "Images must be 2MB or less. Your image was: " + formatBytes(contentLength)});
}
var params = {
classifier_ids: ["Hotdogs_1346435223"],
threshold: .5,
url: url
};
visual_recognition.classify(params, function(err, result) {
if (err){
console.log(err);
return res.status(500).json({msg: "Failure to classify image"});
}
return res.status(200).json(result);
});
});
});
function formatBytes(bytes, decimals) {
if(bytes == 0) return '0 Bytes';
var k = 1000;
var dm = decimals || 2;
var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
var i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
}
function deleteFile(filePath){
fs.unlink(filePath, err => {
if(err)
console.log(err);
});
}
function getURLHeaders(url, callback){
request.head(url, function(err, res, body){
if(err){
console.log("Error getting HEAD for url: " + url);
return callback(err, null);
}
return callback(null, res.headers);
});
}
http.listen(appEnv.port, appEnv.bind);
console.log('App started on ' + appEnv.bind + ':' + appEnv.port);