node.js server, displaying HTML file which has jqGrid plugin included. - html

I have a simple HTML file which includes jqGrid plugin. I am using jqGrid plugin to have a tree grid in my HTML page.
Now, I am trying to host this HTML file in node.js server. My server.js looks like this
var http = require('http');
var fs = require('fs');
var path = require('path');
http.createServer(function (request, response) {
console.log('request starting...');
var filePath = '.' + request.url;
console.log('filePath : '+filePath);
if (filePath == './')
filePath = './tree.html';
var extname = path.extname(filePath);
console.log('extname : '+extname);
var contentType = 'text/html';
switch (extname) {
case '.js':
contentType = 'text/javascript';
break;
case '.css':
contentType = 'text/css';
break;
}
path.exists(filePath, function(exists) {
if (exists) {
fs.readFile(filePath, function(error, content) {
if (error) {
response.writeHead(500);
response.end();
} else {
response.writeHead(200, { 'Content-Type': contentType });
response.end(content, 'utf-8');
}
});
} else {
response.writeHead(404);
response.end();
}
});
}).listen(8125);
So far, I am able to display my HTML content in browser [http://localhost:8125/]
Part of my HTML(tree.html) file looks like this
jQuery("#treegrid").jqGrid({
url: 'tree.json',
datatype: 'json',
//mtype: 'GET',
colNames: [/* "ID", */"Col 1", "Col 2",.. ],
colModel: [/* {
name: 'id',
index: 'id',
width: 1,
hidden: true,
key: true
}, */{ ...
If you can notice, I have specified 'tree.json' as URL attribute to load the tree grid. That is just reading a static file to load the tree grid with sample data.
Problem : Now, when I try to access my HTML file using [http://localhost:8125/]
I get an 404 Not Found error for [http://localhost:8125/tree.json]
Quick Solution : I can specify the relative path of the file 'tree.json' and it works.
Both my HTML file tree.html and tree.json are in the same directory (/tree) and I start my node.js server from command prompt (terminal) like this
tree> node server.js
I would like to know where I can place my tree.json in order to make my HTML work as intended.
Please feel free to ask any clarification.
Thanks in advance

You use the line
var filePath = '.' + request.url;
in your code which seems a little strange. Probably in case of request of 'tree.json' you will have .tree.json as the value of filePath instead of ./tree.json which you probably want to have. I think you should fix the code here.
Moreover it would be good to set 'application/json' as the value of contentType variable in case of .json extension in the same way like you set 'text/javascript' and 'text/css' for '.js' and '.css' files.

Related

How to use a Javascript file to refresh/reload a div from an HTML file?

I am using Node JS and have a JS file, which opens a connection to an API, works with the receving API data and then saves the changed data into a JSON file. Next I have an HTML file, which takes the data from the JSON file and puts it into a table. At the end I open the HTML file in my browser to look at the visualized table and its data.
What I would like to happen is, that the table (or more specific a DIV with an ID inside the table) from the HTML file refreshes itself, when the JSON data gets updated from the JS file. Kinda like a "live table/website", that I can watch change over time without the need to presh F5.
Instead of just opening the HTML locally, I have tried it by using the JS file and creating a connection with the file like this:
const http = require('http');
const path = require('path');
const browser = http.createServer(function (request, response) {
var filePath = '.' + request.url;
if (filePath == './') {
filePath = './Table.html';
}
var extname = String(path.extname(filePath)).toLowerCase();
var mimeTypes = {
'.html': 'text/html',
'.css': 'text/css',
'.png': 'image/png',
'.js': 'text/javascript',
'.json': 'application/json'
};
var contentType = mimeTypes[extname] || 'application/octet-stream';
fs.readFile(filePath, function(error, content) {
response.writeHead(200, { 'Content-Type': contentType });
response.end(content, 'utf-8');
});
}).listen(3000);
This creates a working connection and I am able to see it in the browser, but sadly it doesn't update itself like I wish. I thought about some kind of function, which gets called right after the JSON file got saved and tells the div to reload itself.
I also read about something like window.onload, location.load() or getElementById(), but I am not able to figure out the right way.
What can I do?
Thank you.
Websockets!
Though they might sound scary, it's very easy to get started with websockets in NodeJS, especially if you use Socket.io.
You will need two dependencies in your node application:
"socket.io": "^4.1.3",
"socketio-wildcard": "^2.0.0"
your HTML File:
<script type="module" src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.0.0/socket.io.js"></script>
Your CLIENT SIDE JavaScript file:
var socket = io();
socket.on("update", function (data) { //update can be any sort of string, treat it like an event name
console.log(data);
// the rest of the code to update the html
})
your NODE JS file:
import { Server } from "socket.io";
// other code...
let io = new Server(server);
let activeConnections = {};
io.sockets.on("connection", function (socket) {
// 'connection' is a "magic" key
// track the active connections
activeConnections[socket.id] = socket;
socket.on("disconnect", function () {
/* Not required, but you can add special handling here to prevent errors */
delete activeConnections[socket.id];
})
socket.on("update", (data) => {
// Update is any sort of key
console.log(data)
})
})
// Example with Express
app.get('/some/api/call', function (req, res) {
var data = // your API Processing here
Object.keys(activeConnections).forEach((conn) => {
conn.emit('update', data)
}
res.send(data);
})
Finally, shameful self promotion, here's one of my "dead" side projects using websockets, because I'm sure I forgot some small detail, and this might help. https://github.com/Nhawdge/robert-quest

Displaying html with images using fs

I need to display in my server an html containing some text and stuffs, which are not important here, and the first image found inside the folder given as parameter.
I found another answer where fs.readFile was used to retrieve the html file drectly, with the image already in there, but in this case I need to build an html for every image.
I've tried this, but it doesn't show any image:
var http = require('http');
const fs = require('fs');
function read_dir(req, res, path="./images") {
let image_urls = fs.readdirSync(path);
let src = path.split("").slice(1).join("");
let image = `<img id="image" src="http://localhost:8888${src}/${image_urls[0]}">`;
res.end(image);
}
function onrequest(request, response) {
// Programs what is going to be sent back to the browser.
console.log("HTTP request received");
// Parses command line arguments
var myArgs = process.argv.slice(2);
response.writeHead(200,
{"Content-Type": 'text/html'}
);
response.write(`<h1>SLIDESHOW AREA</h1>`);
read_dir(request, response, myArgs[0]);
}
// The http.createServer() method turns my computer into an HTTP server.
var server = http.createServer(onrequest);
// The server.listen() method creates a listener on the specified port or path.
// server.listen(port, hostname, backlog, callback);
server.listen(8888);
console.log("Listening on http://localhost:8888/");
Okay, so I found out what was missing. If you're one like me that understand really poorly servers, this might be helpful.
<img src="http://localhost:8888/image/jpeg/campus1.jpg">
When the server reads the image src, it sends a GET request with url /image/jpeg/campus1.jpg. Right now the server can display HTML elements, but it cannot display JPEG elements, which is fundamental here.
It's really subtle, the image has to be read from its folder, and be set up correctly before it can be displayed.
So, the correct way to do it is to make a route inside the server that reads images and tells the server that they are of type 'image/jpeg'. At that point, the images are ready and baked to be read by the HTML.
var http = require('http');
const fs = require('fs');
let routes = { "/": main, "/image": fileRouter }
function main(req, res) {
res.writeHead(200, {'Content-Type': 'text/html'});
res.write("<h1>HI</h1>");
res.write("<h2>Here's an image</h2>");
res.end(`<img src="http://localhost:8888/image/jpeg/campus1.jpg">`);
}
function fileRouter(req, res) {
let path = req.url;
console.log(path);
fs.readFile("."+path, function(err, data) {
if(err) {
res.writeHead(500, { 'Content-Type' : 'text/plain' });
res.end('500 - Internal Error');
} else {
res.writeHead(200, { 'Content-Type' : 'image/jpeg' });
res.end(data);
}
});
}
function onrequest(req, res) {
//Parse Request
let url = req.url;
let route = url.split("/")[1];
console.log(req.method, req.url);
//Route Request
if (typeof routes["/" + route] === 'function') {
routes["/" + route](req, res);
} else {
res.writeHead(404); //not found
res.end();
}
}
var server = http.createServer(onrequest);
server.listen(8888);
I wish programming wouldn't require always my head to get dislodged, things don't always make sense, I don't get sometimes why people designed things this way. But well, also love's not always easy. Have a nice day everyone!
This tag <img id="image" src="http://localhost:8888${src}/${image_urls[0]}"> are trying to access to your server a the "http://localhost:8888${src}/${image_urls[0]}" url.
So you need to serve it for the browser to be able to download it.
An jpeg image is served with the 'Content-type: image/jpeg'header, but in the case of large images you need to make a more complex work, like cache memory, streaming, things like that; or the load time of your page will drop down easily.
It is recomended to use services like cloudinary to serve this type of content.

Can't get xlsx to JSON converter to work properly in Node/Express

I am using the package below to try to convert uploaded excel files (.xlsx) to JSON files on my Express web application:
https://www.npmjs.com/package/xlsx-to-json
So here is my form for the user to upload:
form(id = "form1", action="/upload", method="post", enctype="multipart/form-data")
input(type="file", id="control", name="XLupload")
br
input(type="submit" value="Upload" name="Submit")
and here is my routing for the upload back in my main express (app.js) file:
var multer = require('multer');
var upload = multer({dest: './uploads'});
var excel_upload = upload.single('XLupload');
app.post('/upload', excel_upload, function(req, res) {
var fileObject = req.file;
var filePath = fileObject.path;
/*** This is what the file Object looks like when uploaded:
{ fieldname: 'XLupload',
originalname: 'testing.xlsx',
encoding: '7bit',
mimetype: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
destination: './uploads',
filename: 'c1d55ea7d1f6fccc7e3d3d2764db8881',
path: 'uploads\\c1d55ea7d1f6fccc7e3d3d2764db8881',
size: 8013 }
***/
xlsxj({
input: String(filePath),
output: "output.json"
}, function(err, result) {
if (err) {
console.log(err);
} else {
console.log(result);
}
});
});
anyways, to put it shortly, the uploads seem to work fine, that is, they are uploaded to the /uploads folder in the directory. However, the JSON file that I get back from the xlsxj converter is empty and I'm not sure why. I made a small test xlsx file with some words in random cells and it still game me back an empty
[]
in output.json. Anybody can let me know what I am doing wrong?
You can try to use this library XLSX (https://github.com/SheetJS/js-xlsx) and add this code after get workssheet
var roa = XLSX.utils.sheet_to_row_object_array(worksheet);

Need to add a folder to a document library in SharePoint 2013 using REST - SharePoint Hosted app

I'm trying to add a folder to a document library using REST in a SharePoint 2013 SharePoint hosted app. It is hosted in an Office 365 developer site. I'm following the guidelines in MSDN here as well as using the excellent samples on dev.office.com (especially the REST Helper).
While capturing the request during debugging I can't see any problems with my request compared to the documentation and samples. I haven't had issues with any GET requests either.
Here is my request:
var datatext = "{'__metadata': {'type': 'SP.Folder'}, 'ServerRelativeUrl': '" + serverRelativeUrl + foldername + "'}";
$.ajax({
url : $appweburl + "/_api/web/folders",
type: "POST",
data: datatext,
headers: {
"accept": "application/json;odata=verbose",
"X-RequestDigest": $("#__REQUESTDIGEST").val(),
"content-type": "application/json;odata=verbose",
"content-length": datatext.length
},
success: function (data) {
success(data);
},
error: function (data) {
failure(data);
}
});
This generates an error "value does not fall within the expected range"
So this uses "data" instead of "body" because "body" was always generating a JSON Reader error. All of the samples indicate "body" but I found other sources that show this key should be "data" in a POST like this, and it resolves the JSON reader error. I ensure that ServerRelativeUrl leads with a "/" as well as filename.
Any help is greatly appreciated.
EDIT: To follow up on this, I was successful using JSOM only. It turns out that you must add a ListItem to the list and specify the content type to be a folder to achieve this. It works, but it makes me wonder if you have to do something similar in REST - that is rather than use the folder endpoints, do it like adding a listitem to a list. I have not confirmed it.
Usually the error Value does not fall within the expected range occurs since ServerRelativeUrl property was specified in incorrect format.
The following formats are supported:
[Document Library]/[New Folder] list/library relative url
/[Site]/[Web]/[Document Library]/[New Folder] - site collection
relative url
http(s)://[Server]/[Site]/[Web]/[Document Library]/[New Folder]
absolute url
How to create a Folder using SharePoint 2013 REST
Assume the following site structure:
`News` site (under `sites` managed path)
|
`Documents` library
|
`Archive` folder
Then the following examples demonstrate how to create a folder named 2010 in Documents library:
Example 1
createFolder(_spPageContextInfo.webAbsoluteUrl,'/sites/news/Documents/Archive/2011')
.done(function(data)
{
var folder = data.d;
console.log('Folder ' + folder.Name + ' has been created successfully');
})
.fail(
function(error){
console.log(JSON.stringify(error));
});
Example 2
createFolder(_spPageContextInfo.webAbsoluteUrl,'Documents/Archive/2010')
.done(function(data)
{
var folder = data.d;
console.log('Folder ' + folder.Name + ' has been created successfully');
})
.fail(
function(error){
console.log(JSON.stringify(error));
});
where
function executeRequest(url,method,headers,payload)
{
if (typeof headers == 'undefined' || headers == null){
headers = {};
}
headers["Accept"] = "application/json;odata=verbose";
if(method == "POST") {
headers["X-RequestDigest"] = $("#__REQUESTDIGEST").val();
}
var ajaxOptions =
{
url: url,
type: method,
contentType: "application/json;odata=verbose",
headers: headers
};
if(method == "POST") {
ajaxOptions.data = JSON.stringify(payload);
}
return $.ajax(ajaxOptions);
}
function createFolder(webUrl,folderUrl)
{
var url = webUrl + "/_api/web/folders";
var folderPayload = { '__metadata': { 'type': 'SP.Folder' }, 'ServerRelativeUrl': folderUrl};
return executeRequest(url,'POST',null,folderPayload);
}

AngularJS File Upload to Backend Express Server

I am trying to do a file upload using angularjs, using angular-file-upload library (https://github.com/danialfarid/angular-file-upload)
Here is my code
// ===============================My HTML File===========================
<input type="file" ng-file-select="onFileSelect($files)">
// ===============================My Controller==========================
var $scope.formObj = {
name: "Test"
};
var fileToUpload;
$scope.onFileSelect = function (file) {
fileToUpload = file[0];
};
// POSt request to /api/items
$scope.addItem = function() {
console.log($scope.formObj);
$scope.upload = $upload.upload({
url: '/api/items',
method: 'POST',
data: { myObj: $scope.formObj },
file: fileToUpload
}).success(function(data, status, headers, config) {
console.log("success");
});
};
// ================================My Backend=============================
// This is the function that will receive POST request to /api/items
exports.create = function(req, res) {
console.log(req.body); // req.body is just an empty object. ==> {}
// apparently, I found all the data to be in req._readableState.buffer[0]
// in the form of a buffer
var buffer = req._readableState.buffer[0];
// trying to console.log the buffer.toString, resulting in something similar to this
// { name: "Test", image: Object }
console.log(buffer.toString());
return res.send(200);
};
So my backend received the formObj with all its properties and values, however, the actual file data itself, whether in the form of buffer, or base64, or whatever, never gets received.
I wonder why. This is my first time working with file uploading, so I don't understand the concept.
Please point me in the right direction
If you are using Latest version of Express, you'd notice that
app.use(express.multipart()); is no longer bundled with express.
So do the following configuration changes. in express.js
var multer = require('multer');
app.use(multer({ dest: './uploads/'}));
You'd find that after doing this you would find the data and file , in req.body req.file respectively.
Hope it helps