built.io
Version:
SDK for Built.io Backend
282 lines (266 loc) • 9.37 kB
JavaScript
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
};