UNPKG

built.io

Version:

SDK for Built.io Backend

282 lines (266 loc) 9.37 kB
var when = require('when'); var https = require('https'); var Events = require('../events'); var node = require('../node'); var utility = require('./utility'); var constants = require('../constants'); var fs = node.fs; // var https = node.https; /** Converts a list of parameters to forum data - `fields` - a property map of key value pairs - `file` - a list of property maps of content - `contentType` - the contentType of file data - `keyName` - the name of the key corresponding to the file - `fileName` - the name of the value corresponding to the file - `data` - the data of the file */ function getFormDataForPost(fields, file) { function encodeFieldPart(boundary,name,value) { var return_part = '--' + boundary + '\r\n'; return_part += 'Content-Disposition: form-data; name="' + name + '"\r\n\r\n'; return_part += value + '\r\n'; return return_part; } function encodeFilePart(boundary, contentType, name, filename) { var return_part = '--' + boundary + '\r\n'; return_part += 'Content-Disposition: form-data; name="' + name + '"; filename="' + filename + '"\r\n'; return_part += 'Content-Type: ' + contentType + '\r\n\r\n'; return return_part; } var boundary = Math.random(); var post_data = []; if (fields) { for (var key in fields) { var value = fields[key]; post_data.push(new Buffer(encodeFieldPart(boundary, key, value), 'ascii')); } } if (file) { for (var key in file) { var value = file[key]; post_data.push(new Buffer(encodeFilePart(boundary, value.contentType, value.keyName, value.fileName), 'ascii')); post_data.push(new Buffer(value.data, 'utf8')) } } post_data.push(new Buffer('\r\n--' + boundary + '--'), 'ascii'); var length = 0; for(var i = 0; i < post_data.length; i++) { length += post_data[i].length; } var params = { postdata : post_data, length : length, headers : { 'Content-Type': 'multipart/form-data; boundary=' + boundary, 'Content-Length': length } }; return params; } /** Sends a post form request via http - `fields` - a property map of key value pairs - `file` - a list of property maps of content - `type` - the type of file data - `keyName` - the name of the key corresponding to the file - `fileName` - the name of the value corresponding to the file - `data` - the data of the file - `options` is a set of options - host - port - path - method - encoding - `headers` headers to be sent with the request - `callback` - callback to handle the response */ function postData(fields,file,options,headers) { var deferred = when.defer(); var headerparams = getFormDataForPost(fields, file); var totalheaders = headerparams.headers; for (var key in headers) totalheaders[key] = headers[key]; var post_options = { host: options.host, path: options.path, method: options.method || 'POST', headers: totalheaders }; Events.trigger("upload:start"); var request = https.request(post_options, function(response) { response.body = ''; if(response.setEncoding) response.setEncoding(options.encoding); response.on('data', function(chunk){ response.body += chunk; }); response.on('end', function() { Events.trigger("upload:end",JSON.parse(response.body)); deferred.resolve(response.body); }); response.on('error',function(){ deferred.reject(response); }) }); for (var i = 0; i < headerparams.postdata.length; i++) { request.write(headerparams.postdata[i]); } request.end(); return deferred.promise; } function checkNInsertFile(data, file){ // In this type user provides a encoded file, filename and a optional contentType if (isRawDataUpload(file)) { data['encodedUpload'] = constructEncodedUpload(file) } else if(utility.isBrowser()){ if(typeof file[0] !== "undefined"){ //for browsers that store files in array data['file'] = file[0]; } else if(file && (file.nodeType === 1 || file.nodeType === 9) || (typeof FormData !== 'undefined' && file instanceof FormData)||(typeof File !=='undefined' && file instanceof File)) { data['file'] = file; }else { throw new Error('The parameter is not valid or not supported by the platform. Please pass an html input elment.'); } }else{ if(file.indexOf('://')>=0){ data['file'] = file; }else{ if(fs.existsSync(file)){ if(fs.statSync(file).isFile()){ data['file'] = file; }else{ throw new Error("invalid file path: "+file); } } } } return data; } function makePostRequest(contentType, fileName, data, param, keyName, model){ var options = model.getHttpRequestOptions(model); var headers = model.getCombinedHeaders(model); var stringifiedParams = JSON.stringify(param); var file = [{ contentType: contentType, keyName : keyName, fileName : fileName, data : data }]; return postData(stringifiedParams, file, options, headers) } function uploadViaFormData(adaptor, data, headers, url, param, method, keyName){ //Upload events in Restfull Adaptor var reqObj = {}; var formData = getFormDataObject(data, keyName); reqObj['formData'] = formData; reqObj['headers'] = headers; reqObj['url'] = url; formData.append("PARAM" ,JSON.stringify(param)); delete reqObj.headers["Content-Type"]; // As getCombined headers returns Content-Type as application/json return adaptor.makeXMLHttpRequest(reqObj) } function createIFrame(uploadNum){ var iFrame = document.createElement("iframe"); iFrame.setAttribute("id" , "builtIFrame"+uploadNum); iFrame.setAttribute("name" , "builtIFrame"+uploadNum); iFrame.setAttribute("width" , "0"); iFrame.setAttribute("height", "0"); iFrame.setAttribute("style" , "display:none"); return iFrame; } function createUploadForm(url,headers,method,params,file,keyName,uploadNum){ var uploadForm = document.createElement('form'); uploadForm.setAttribute('id' ,'builtUploadForm'+uploadNum); uploadForm.setAttribute("target", 'builtIFrame'+uploadNum); uploadForm.setAttribute("method", "post"); uploadForm.setAttribute("height","0"); uploadForm.setAttribute("width","0"); uploadForm.setAttribute("style","display:none"); uploadForm.setAttribute("enctype", "multipart/form-data"); uploadForm.setAttribute("encoding", "multipart/form-data"); uploadForm.setAttribute("action",url+'.postmessage'); uploadForm.appendChild(createInputElement("PARAM",params)); uploadForm.appendChild(createInputElement("postmessage_payload",uploadNum)); // uploadForm.appendChild(createInputElement("_method",method)); uploadForm.appendChild(createInputElement("host",(document.location.origin?document.location.origin:(document.location.protocol+"//"+document.location.host)))); file.setAttribute('name',keyName); uploadForm.appendChild(file); for(var header in headers){ uploadForm.appendChild(createInputElement(header.toUpperCase(),headers[header])); } return uploadForm; } //===== PUBLIC ================================================================ function createInputElement(name, val ) { var inputElement; inputElement = document.createElement("input"); inputElement.type = "hidden"; inputElement.name = name; inputElement.value = val; return inputElement; } function getFormDataObject(data, keyName){ if(data instanceof FormData){ return data; } else if(typeof File !== "undefined" && data instanceof File){ var formd = new FormData(); formd.append(keyName,data); return formd; } else if(data && (data.nodeType === 1 || data.nodeType === 9)) { var formd = new FormData(); if (data.getAttribute('type') == 'file') { formd.append(keyName, data.files[0]); return formd; }else { throw new Error("input file element required"); } } else{ throw new Error("HTML input file element or FormData or File required"); } } function constructEncodedUpload(file){ var fileExtension = /\.([^.]*)$/.exec(file.name); if (fileExtension) { fileExtension = fileExtension[1].toLowerCase(); } var assumedExt = file.contentType || constants.MIME_TYPES[fileExtension] || "text/plain"; if(file.bytes){ // File is provided in bytes format or Buffer return { bytesData : file.bytes, contentType : assumedExt, name : file.name } }else if(file.base64){ // File is provided in base64 format var base64Enc = file.base64; var matches = constants.BASE_64_REGEX.exec(base64Enc); if (matches && matches.length > 0) { base64Enc = (matches.length === 4 ? matches[3] : matches[2]) assumedExt = matches[1] } var buf = new Buffer(base64Enc, 'base64'); return { bytesData : buf, contentType : assumedExt, name : file.name } } else{ throw new Error("Invalid file format") } } function isRawDataUpload(file){ return !!(utility.isObject(file) && file.name && (file.base64 || file.bytes)) } module.exports = { getFormDataForPost : getFormDataForPost, postData : postData, checkNInsertFile : checkNInsertFile, makePostRequest : makePostRequest, uploadViaFormData : uploadViaFormData, createIFrame : createIFrame, createUploadForm : createUploadForm };