Error: PDFDocument: stream must have data - node.js

I am using pdf.js to parse pdf files. First I am uploading the file and then trying to parse that file.I am passing the url to parse function to read it in PDFJS.getDocument(url)
If I don't use the upload part and hardcode the URL of the pdf file it works.
Code :
var parse = function(payload,callback){
var data = payload;
if(data.file){
var name = data.file.hapi.filename;
var ext = name.split('.');
var extension = ext[1];
if(extension == "pdf"){
var path = __dirname + "/uploads/" + name;
checkFileExist();
var file = fs.createWriteStream(path);
file.on('error', function (err) {
console.error(err)
});
data.file.pipe(file);
var fileName = data.file.hapi.filename;
console.log(fileName);
var fileAbsolutepath = __dirname + "/uploads/" + fileName ;
console.log(fileAbsolutepath);
var parser = script.pdfParser(fileAbsolutepath,function(err,resp){
if(err){
callback(err);
}
else {
callback(resp);
}
})
callback(JSON.stringify(fileName));
}
else{
console.log("Invalid fileType");
callback(JSON.stringify("Invalid FileType"));
}
}
}
var checkFileExist = function() {
var path = __dirname + '/uploads';
fs.exists(path, function(exists) {
if (exists === false) fs.mkdirSync(path);
});
};
exports.pdfParser = function(url,callback){
PDFJS.workerSrc = 'pdf.worker.js';
PDFJS.getDocument(url).then(function (pdf) {
var pdfDocument = pdf;
}}
The file is uploaded properly with expected file size in uploads folder still I get error : "Error: PDFDocument: stream must have data"

To parse files with pdf.js, rather than loading the file with PDFJS.getDocument, try converting the pdf file to an arrayBuffer or Uint8Array, and use that to create a new LocalPdfManager object. Then you can call the LocalPdfManager's methods directly to parse the pdf.
Something like this:
import { LocalPdfManager } from 'pdfjs-dist/lib/core/pdf_manager';
pdfManager = new LocalPdfManager(1, arrayBuffer, '', {}, '');
// parameters = (docId, data, password, evaluatorOptions, docBaseUrl)
pdfManager.ensureDoc('parseStartXRef', []); // [] = arguments
pdfManager.ensureDoc('parse', false); // false = recoveryMode
pdfManager.ensureDoc('numPages');
pdfManager.ensureDoc('fingerprint');
Then look at pdfManager.pdfDocument for the parsed pdf data.
For example, the main "/Catalog" entry will be in pdfManager.pdfDocument.catalog.catDict.
I've used this method to successfully parse and modify pdf files locally in a browser. I haven't tried it on a server with node.js, but I expect it should work the same.

Related

how to send file from specified path in response from local storage using node.js

I Have path tmp\daily_gasoline_report\9. where 9 is uniqe-id which will be different every time I want to send image from that folder in response. how can I send that file in response ??
I have tried with fs
if (!req.body.path) {
logger.warn(error.MANDATORY_FIELDS);
return res.status(500).send(error.MANDATORY_FIELDS)
}
let directory_name = req.body.path;
let filenames = fs.readdirSync(directory_name);
console.log("\nFilenames in directory:");
filenames.forEach((file) => {
console.log("File:", file);
});
let result = error.OK
result.data = filenames
logger.info(result);
return res.status(200).send(result)
I get only files name not files but now I have files name which comes in Url with path and file name from front end so, how can I send file from path in response
I got the Answer
this worked for me to get single image from folder
const fs = require('fs');
const url = require('url')
let query = url.parse(req.url, true).query;
let pic = query.image;
let id = query.id
let directory_name = "tmp/daily_gasoline_report/" + id + "/" + pic
let filename = fs.existsSync(directory_name);
if (filename) {
//read the image using fs and send the image content back in the response
fs.readFile(directory_name, function (err, content) {
if (err) {
res.writeHead(400, { 'Content-type': 'text/html' })
console.log(err);
res.end("No such image");
} else {
//specify the content type in the response will be an image
res.writeHead(200);
res.end(content);
}
});
Try this,
let directory_name = req.body.path;
let filenames = fs.readdirSync(directory_name);
let resultantArr = [];
console.log("\nFilenames in directory:");
filenames.forEach((file) => {
console.log("File:", file);
var fr = new FileReader();
fr.onload = function () {
var data = fr.result;
var array = new Int8Array(data);
resultantArr.push(JSON.stringify(array, null, ' '));
};
fr.readAsArrayBuffer(file);
});
let result = error.OK
result.data = resultantArr;
logger.info(result);
return res.status(200).send(result)
#Arya Here is the code-snippet to deal with image file:
let fr = new FileReader();
fr.onloadend = function(event) {
let base64Data = fr.result;
let arrayBufferView = new Uint8Array(base64Data);
let blob = new Blob( [ arrayBufferView ], { type: file.type } );
resultantArr.push(blob);
}
fr.readAsArrayBuffer(file);
And later on to read the blob values of an array and create image url out of it, you can do this:
let urlCreator = window.URL || window.webkitURL || {}.createObjectURL;
let imageUrl = urlCreator.createObjectURL( blob );
you will need to zip all files in the path and send zip folder, you cannot send multiple files.
Also cross check your requirements, if file size goes to big number your application will crash

HTML to PDF with Node.js and Electron.js

Here are the relevant code.
let Name = moment().unix() + ".pdf";
var html = fs.readFileSync('./test/businesscard.html', 'utf8');
let filename = "C:\\App\\Register\\pdf\\" + Name;
pdf.create(html, options).toFile(filename, function (err, response) {
if (err) {
res.status(403).json({
message: 'error'
})
} else {
res.status(200).json({
message: 'success'
})
}
}
it's working fine on dev version and create PDF file. But when i create a
electron build-pack, the pdf file not generated.
If any solution is available then it will be a big help
You should use an absolute path for packaged application by using app.getAppPath().
Remplace this line
var html = fs.readFileSync('./test/businesscard.html', 'utf8');
By this
var html = fs.readFileSync(path.join(app.getAppPath(), '/test/businesscard.html', 'utf8'));
And not forgot to add
const path = require('path')
const app = require('electron').remote.app

Gulp: Abnormal behavior of program

I'm new to Gulp and I'm having a problem with gulp,here are some points that I want to be done
I want to lookup for a file that has an .storyboard extension
(it is already DONE)
I want to perform a task whenever a certain file's content is
changed,
I want to Watch that file and when something is being changed in
that file
I want to rewrite its content by removing all other content that was
already in the file.
When I make changes in file with .storyboard extension, it just keep on displaying a message done, file has been saved
Here is my Code:
//fs to read and write files while path is for iterating directories
fs = require('fs'),
path = require('path')
//DomParser to Parse Xml
var DOMParser = new (require('xmldom')).DOMParser({ normalizeTags: { default: false } });
//Gulp for detecting changes
var gulp = require('gulp')
var mainStoryBoardFile;
function crawl(dir) {
// console.log('[+]', dir);
var files = fs.readdirSync(dir);
for (var file in files) {
var next = path.join(dir, files[file]);
//iterate through files to check whether next is a file or direcory
if (fs.lstatSync(next).isDirectory()) {
//if its a directory dive into it
crawl(next);
} else if (next.indexOf('.storyboard') >= 0) {
//if its a file just check it whether it is a .storyboard file or not
mainStoryBoardFile = next;
mainStoryBoardFile = mainStoryBoardFile.replace(/\\/g, "/");
};
}
}
//calling function
crawl(__dirname);
var newFilePath = './data.xml'
var document;
var dataFound;
//What to do
gulp.task('read', function (done) {
dataFound = fs.readFileSync(mainStoryBoardFile, "utf-8");
document = DOMParser.parseFromString(
dataFound.toString()
);
done();
});
gulp.task('write', function (done) {
fs.writeFile(mainStoryBoardFile, '', function () { console.log('done') })
fs.writeFile(mainStoryBoardFile, document, (err) => {
if (err) throw err;
console.log('The file has been saved!');
});
done();
});
gulp.task('watch', function (done) {
gulp.watch(mainStoryBoardFile, gulp.series('read', 'write'));
});
Here is a solution to solve this problem, You can watch changes on a single file and you can also perform some sort of function whenever a file is changed. in xml case, you can watch a file, when it changes you can add new properties or attributes or you can create new elements in xml file.
//Dependencies
//fs to read and write files while path is for iterating directories
var fs = require('fs'),
path = require('path'),
DOMParser = new (require('xmldom')).DOMParser({ normalizeTags: { default: false } }),
gulp = require('gulp'),
arrayOfControls = require('./object.json'),
RandExp = require('randexp');
console.log("GulpService has been Started\n");
function crawl(dir) {
var files = fs.readdirSync(dir);
for (var file in files) {
var next = path.join(dir, files[file]);
//iterate through files to check whether next is a file or direcory
if (fs.lstatSync(next).isDirectory()) {
//if its a directory dive into it
crawl(next);
} else if (next.indexOf('.storyboard') >= 0) {
//if its a file just check it whether it is a .storyboard file or not
mainStoryBoardFile = next;
mainStoryBoardFile = mainStoryBoardFile.replace(/\\/g, "/");
}
}
}
//calling function
crawl(__dirname);
var mainStoryBoardFile;
var document, dataFound;
function readWrite() {
crawl(__dirname);
dataFound = fs.readFileSync(mainStoryBoardFile, "utf-8");
document = DOMParser.parseFromString(
dataFound.toString()
);
fs.writeFileSync(mainStoryBoardFile, '', function () {
console.log('done')
});
fs.writeFileSync(mainStoryBoardFile, document, (err) => {
if (err) throw err;
console.log('The file has been saved!');
});
}
var watcher = gulp.watch(mainStoryBoardFile);
watcher.on('change', function (path, stats) {
readWrite();
console.log('File ' + path + ' was changed');
watcher.unwatch(mainStoryBoardFile);
watcher.add(mainStoryBoardFile);
});

On which format send file to save it on gridfs?

Hy every one,
Please , i 'm study on a project using nodeJS, and i would like to know , in which format my node client must send the file to the server ( is it in base64 format or else ?).
my client is :
//client.js
$('#file').on('change', function(e){
encode64(this);
});
function encode64(input) {
if (input.files){
chap.emit('test', { "test" : input.files[0] });
var FR= new FileReader();
FR.readAsDataURL(input.files[0]);
FR.onload = function(e) {
chap.emit('test', { "test" : e.target.result } );
}
}
}
My server side is :
socket.on('test', function(e){
var gs = new gridStore(db, e.test,"w");
gs.writeFile(new Buffer(e.test,"base64"), function(err,calb){
if (!err)
console.log('bien passe');
else
console.log('erreur');
});
});
But this doesn't work , i get this error :
TypeError: Bad argument
at Object.fs.fstat (fs.js:667:11)
Any one could help me ?
Normally this is how you store into gridFs . I have used it to store files. hope it works.
fs = require('fs'),
var gfs = require('gridfs-stream');
var form = new multiparty.Form();
form.parse(req, function (err, fields, files) {
var file = files.file[0];
var filename = file.originalFilename; //filename
var contentType = file.headers['content-type'];
console.log(files)
var tmpPath = file.path ;// temporary path
var writestream = gfs.createWriteStream({filename: fileName});
// open a stream to the temporary file created by Express...
fs.createReadStream(tmpPath)
// and pipe it to gfs
.pipe(writestream);
writestream.on('close', function (file) {
// do something with `file`
res.send(value);
});
})

Modify image obtained from loopback-component-storage

I am using loopback for storing Image to the server.
I want to modify the file name of the file before getting saved to the server.
Also I want to convert it to another thumbnail form before getting saved.
Here is how I am doing.
At client side
Upload.upload(
{
url: '/api/containers/container_name/upload',
file: file,
fileName: "demoImage.jpg",
//Additional data with file
params:{
orderId: 1,
customerId: 1
}
});
At Server Side I am receiving the query "params" but not getting the "File Name"
My Storage model name is container
Container.beforeRemote('upload', function(ctx, modelInstance, next) {
//OUPTUTS: {orderId:1, customerId:1]}
console.log(ctx.req.query);
//Now I want to change the File Name of the file.
//But not getting how to do that
next();
})
How to change the File name of the File getting saved at the server?
I figured it out.
We have to define a custom function getFileName in boot/configure-storage.js.
Suppose my datasource for loopback-component-storage is presImage.
server/boot/configure-storage.js
module.exports = function(app) {
//Function for checking the file type..
app.dataSources.presImage.connector.getFilename = function(file, req, res) {
//First checking the file type..
var pattern = /^image\/.+$/;
var value = pattern.test(file.type);
if(value ){
var fileExtension = file.name.split('.').pop();
var container = file.container;
var time = new Date().getTime();
var query = req.query;
var customerId = query.customerId;
var orderId = query.orderId;
//Now preparing the file name..
//customerId_time_orderId.extension
var NewFileName = '' + customerId + '_' + time + '_' + orderId + '.' + fileExtension;
//And the file name will be saved as defined..
return NewFileName;
}
else{
throw "FileTypeError: Only File of Image type is accepted.";
}
};
}
common/models/container.js
Now suppose my container model is container.
module.exports = function(Container) {
Container.afterRemote('upload', function(ctx, modelInstance, next) {
var files = ctx.result.result.files.file;
for(var i=0; i<files.length; i++){
var ModifiedfileName = files[i].name;
console.log(ModifiedfileName) //outputs the modified file name.
} //for loop
next();
}); //afterRemote..
};
Now for converting it images to Thumbnail size
Download the quickthumb
Here is how to use it with loopback.
This code is copied directly from Loopback thumbnail view
common/models/container.js
module.exports = function(Container) {
var qt = require('quickthumb');
Container.afterRemote('upload', function(ctx, res, next) {
var file = res.result.files.file[0];
var file_path = "./server/storage/" + file.container + "/" + file.name;
var file_thumb_path = "./server/storage/" + file.container + "/thumb/" + file.name;
qt.convert({
src: file_path,
dst: file_thumb_path,
width: 100
}, function (err, path) {
});
next();
});
};
Piggybacking on the answer above, this configure-storage enables the file name to be set explicitly via req.params.filename and to default to the existing name if none is provided.
configure-storage.js
module.exports = function(app) {
//Function for checking the file type..
app.dataSources.storage.connector.getFilename = function(file, req, ignoreRes) {
if (!req.params.filename) {
return file.name
}
var fileExtension = file.name.split('.').pop()
return req.params.filename + '.' + fileExtension
};
}

Resources