I have the #pdftron node module installed in a test Node (Hapi) application on my Mac. I'm trying to generate a PDF file from a HTML string but the saved file is 0 KB. I've tried this two ways:
By implementing the example code in the GET handler for a route
configured in index.js
By running the sample scripts that are
installed at
node_modules/#pdftron/pdfnet-node/samples/HTML2PDFTest/NODEJS/HTML2PDFTest.js
In both cases, any new PDFs that are saved have a size of 0KB and any existing PDFs that are supposed to be modified by the process remain unchanged.
I've checked that the html2pdf module library path is being set correctly.
The route handler code is as follows, which is in accordance with example code provided by PDFTRon.
server.route({
method: 'GET',
path: '/pdftron/html',
handler: (request, h) => {
const { PDFNet } = require('#pdftron/pdfnet-node/lib/pdfnet.js')
const main = async () => {
await PDFNet.initialize()
await PDFNet.HTML2PDF.setModulePath('node_modules/#pdftron/pdfnet-node/lib')
const output_path = '/tmp/'
try {
const html2pdf = await PDFNet.HTML2PDF.create();
const doc = await PDFNet.PDFDoc.create();
const html = '<html><body><h1>Heading</h1><p>Paragraph.</p></body></html>'
html2pdf.insertFromHtmlString(html);
await html2pdf.convert(doc);
doc.save(output_path.concat('pdf2html.pdf'), PDFNet.SDFDoc.SaveOptions.e_linearized);
} catch (err) {
console.log(err)
}
}
PDFNet.runWithCleanup(main, 0).then(function () { PDFNet.shutdown(); })
return 'PDF2HTML Test'
}
})
Any thoughts/suggestions would be much appreciated.
Update on this - I had feedback from PDFTron to say that there is currently an issue with the current stable release of the Mac OS build and that they are addressing it.
In the meantime, they pointed me to the nightly experimental builds here. I downloaded and installed a recent experimental build and the PDF files now save OK using that.
Related
I am using minio to manage the files
const getMinioClient = () => {
const minioClient = new Minio.Client({
endPoint: '127.0.0.1',
port: 9000,
useSSL: false,
accessKey: 'minioadmin',
secretKey: 'minioadmin'
});
return minioClient;
};
uploadFile(bucketName, newFileName, localFileLocation,metadata={}) {
return new Promise((resolve, reject) => {
const minioClient = getMinioClient();
//'application/octet-stream'
minioClient.fPutObject(bucketName, newFileName, localFileLocation, metadata , (err, etag) => {
if (err) return reject(err);
return resolve(etag);
});
});
}
with the following code I can upload the file, after successfully uploading it returns me only with etag, but I want to get the download link, how would I get it directly without searching the filename again.
You won't be able to get something like Public URL/Link for accessing images unless you ask for it to manually generate a time limited download URL using something like:
https://min.io/docs/minio/linux/reference/minio-mc/mc-share-download.html#generate-a-url-to-download-object-s
One workaround is to let nginx directly access the location you are uploading your files to:
https://gist.github.com/harshavardhana/f05b60fe6f96803743f38bea4b565bbf
After you have successfully written your file with your code above, you can use presignedUrl method to generate the link to your image.
An example for Javascript is here: https://min.io/docs/minio/linux/developers/javascript/API.html#presignedUrl:~:text=//%20presigned%20url%20for%20%27getObject%27%20method.%0A//%20expires%20in%20a%20day.%0AminioClient.presignedUrl(%27GET%27%2C%20%27mybucket%27%2C%20%27hello.txt%27%2C%2024*60*60%2C%20function(err%2C%20presignedUrl)%20%7B%0A%20%20if%20(err)%20return%20console.log(err)%0A%20%20console.log(presignedUrl)%0A%7D)
In any case you have to set an expiration time. Here or you set a very long time, which is suitable to your app or if you have a backend, require the images from Frontend through the backend with the getObject method: getObject(bucketName, objectName, getOpts[, callback]).
https://min.io/docs/minio/linux/developers/javascript/API.html#presignedUrl:~:text=getObject(bucketName%2C%20objectName%2C%20getOpts%5B%2C%20callback%5D)
If you have only a few number of static images to show in your app, (which are not uploaded by your app), you can also create the links manually with tme minio client or from the Minio-UI.
I'm able to create a folder if it not exists and save a newly written file in that folder previously. but after updating to latest nativescript the same code was not working and not give error properly.
and also I'm getting an error
Error: android.util.AndroidRuntimeException: Calling startActivity() from >outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. >Is this really what you want?
const fileSystemModule = require("tns-core-modules/file-system");
const documents = fileSystemModule.knownFolders.documents();
documents._path = "/storage/emulated/0/";
const folder = documents.getFolder('Reports/sample/');
const file = folder.getFile('fileName.xlsx');
file.writeText(viewModel.get("fileTextContent") || html_content)
.then((result) => {
return file.readText()
.then((res) => {
var toast = Toast.makeText("Exported to Excel Succesfully");
toast.show();
return res;
});
}).then((result) => {
console.log("---result---");
console.log(result); // im getting result, a html string
var intent = new android.content.Intent(android.content.Intent.ACTION_VIEW);
intent.setDataAndType(android.net.Uri.fromFile(new java.io.File(file._path)), "application/vnd.ms-excel");
application.android.context.startActivity(android.content.Intent.createChooser(intent, "Open Excel..."));
}).catch((err) => {
console.log(err);
});
before updating it was working fine. but now I don't know what happened to this.
It's a new requirement from Android itself. You must add FLAG_ACTIVITY_NEW_TASK flag to your intent.
With Android 9, you cannot start an activity from a non-activity context unless you pass the intent flag FLAG_ACTIVITY_NEW_TASK. If you attempt to start an activity without passing this flag, the activity does not start, and the system prints a message to the log.
intent.addFlags(android.content.Intent.FLAG_ACTIVITY_NEW_TASK);
How can I delete an image's file from the server using Parse Cloud Code. I am using back4app.com
After Deleting Image Row
I am getting the images urls, then calling a function to delete the image using its url
Parse.Cloud.afterDelete("Image", function(request) {
// get urls
var imageUrl = request.object.get("image").url();
var thumbUrl = request.object.get("thumb").url();
if(imageUrl!=null){
//delete
deleteFile(imageUrl);
}
if(thumbUrl!=null){
//delete
deleteFile(thumbUrl);
}
});
Delete the image file from the server
function deleteFile(url){
Parse.Cloud.httpRequest({
url: url.substring(url.lastIndexOf("/")+1),
method: 'DELETE',
headers: {
'X-Parse-Application-Id': 'xxx',
'X-Parse-Master-Key': 'xxx'
}
}).then(function(httpResponse) {
console.log(httpResponse.text);
}, function(httpResponse) {
console.error('Request failed with response code ' + httpResponse.status);
});
}
for security reasons, not is posible to delete directly the image from Back4App, using DELETE from SDK or REST API. I believe that you can follow the guide below:
https://help.back4app.com/hc/en-us/articles/360002327652-How-to-delete-files-completely-
After struggling with this for a while it seems to be possible through cloud function as mentioned here. One need to use MasterKey in the cloud code:
Parse.Cloud.define('deleteGalleryPicture', async (request) => {
const {image_id} = request.params;
const Gallery = Parse.Object.extend('Gallery');
const query = new Parse.Query(Gallery);
try {
const Image = await query.get(image_id);
const picture = Image.get('picture');
await picture.destroy({useMasterKey: true});
await Image.destroy();
return 'Image removed.';
} catch (error) {
console.log(error);
throw new Error('Error deleting image');
}
});
For me it was first confusing since I could open the link to that file even after I deleted the reference object in the dashboard, but then I found out that the dashboard is not calling Parse.Cloud.beforeDelete() trigger for some reason.
Trying to download the data from the url after deleting the file through the cloud code function returns 0kB data and therefore confirms that they were deleted.
Slack themes are available in the web app using Stylish see https://userstyles.org/styles/browse?search_terms=slack
However there must be a way to use them on the Desktop application. What is the hack?
UPDATED LATEST! Slack desktop app now supports dark mode natively!
Just got to preferences cmd+, and select Themes > Dark
UPDATED, previous hacks stopped working with release of 4.0.0.
This solution works as of July 18, 2019
see https://github.com/LanikSJ/slack-dark-mode
You may need to see instructions on https://github.com/LanikSJ/slack-dark-mode/issues/80
I will likely update this answer again when I have time to fork the repo I've posted above and improve upon it.
I've written a sort of small "plugin framework", where you just run a shell script to patch your slack install, and then you get the ability to enable any number of "plugins" I've written for the desktop app, one of which is a dark theme. There are instructions in the README if you'd like to load your own CSS files you've found elsewhere as well.
https://github.com/glajchs/slack-customizations
Here's my script to toggle between light and dark mode automatically at sunrise/sunset. Append the script at the end of /Applications/Slack.app/Contents/Resources/app.asar.unpacked/src/static/ssb-interop.js and don't forget to update the LOCATION based on your actual location.
document.addEventListener('DOMContentLoaded', async function() {
// supply your location here, use e.g. https://www.latlong.net/ to find it
const LOCATION = [50.075539, 14.437800]
const MS_IN_DAY = 24 * 60 * 60 * 1000
const initTheme = themeCssUrl => new Promise(resolve => $.ajax({
url: themeCssUrl,
success: css => {
const styleJqueryEl = $('<style>').html(css).appendTo('head')
const styleElement = styleJqueryEl[0]
styleElement.disabled = true
resolve(styleElement)
}
}))
const loadTimeInfo = ([latitude, longitude]) => new Promise(resolve => $.ajax({
// courtesy of https://sunrise-sunset.org/api
url: `https://api.sunrise-sunset.org/json?lat=${latitude}&lng=${longitude}&formatted=0`,
success: ({ results: { sunrise, sunset } }) => resolve({
sunrise: Number(new Date(sunrise)),
sunset: Number(new Date(sunset)),
expires: Math.ceil(Date.now() / MS_IN_DAY) * MS_IN_DAY
})
}))
const updateTheme = (styleElement, timeInfo) => {
const now = Date.now()
const { sunrise, sunset } = timeInfo
styleElement.disabled = now >= sunrise && now < sunset
}
const darkModeStyle = await initTheme('https://raw.githubusercontent.com/mattiacantalu/Slack-Dark-Mode/master/dark-mode.css')
let timeInfo = await loadTimeInfo(LOCATION)
updateTheme(darkModeStyle, timeInfo)
// can't simply `setTimeout` to the next update time - if the app is sleeping at that time, the call seems to be lost
window.setInterval(async () => {
if (Date.now() > timeInfo.expires) {
timeInfo = await loadTimeInfo(LOCATION)
}
updateTheme(darkModeStyle, timeInfo)
}, 5 * 60 * 1000)
})
Note that as this process directly modifies the application files, it needs to be repeated after every Slack update.
This answer does not solve the desktop app question but can be used as a browser only based solution.
Use Chrome instead of downloadable Slack app
Install Dark Reader chrome add-on
Open Slack url (eg. https://team_name.slack.com/) in Chrome instead of app
I'm building a super simple server in node and in my onRequest listener I'm trying to determine if I should serve a static file (off the disk) or some json (probably pulled from mongo) based on the path in request.url.
Currently I'm trying to stat the file first (because I use mtime elsewhere) and if that doesn't fail then I read the contents from disk. Something like this:
fs.stat(request.url.pathname, function(err, stat) {
if (!err) {
fs.readFile(request.url.pathname, function( err, contents) {
//serve file
});
}else {
//either pull data from mongo or serve 404 error
}
});
Other than cacheing the result of fs.stat for the request.url.pathname, is there something that could speed this check up? For example, would it be just as fast to see if fs.readFile errors out instead of the stat? Or using fs.createReadStream instead of fs.readFile? Or could I potentially check for the file using something in child_process.spawn? Basically I just want to make sure I'm not spending any extra time messing w/ fileio when the request should be sent to mongo for data...
Thanks!
var fs = require('fs');
fs.exists(file, function(exists) {
if (exists) {
// serve file
} else {
// mongodb
}
});
I don't think you should be worrying about that, but rather how can you improve the caching mechanism. fs.stat is really ok for file checking, doing that in another child process would probably slow you down rather then help you here.
Connect implemented the staticCache() middleware a few months ago, as described in this blog post: http://tjholowaychuk.com/post/9682643240/connect-1-7-0-fast-static-file-memory-cache-and-more
A Least-Recently-Used (LRU) cache algo is implemented through the
Cache object, simply rotating cache objects as they are hit. This
means that increasingly popular objects maintain their positions while
others get shoved out of the stack and garbage collected.
Other resources:
http://senchalabs.github.com/connect/middleware-staticCache.html
The source code for staticCache
this snippet can help you
fs = require('fs') ;
var path = 'sth' ;
fs.stat(path, function(err, stat) {
if (err) {
if ('ENOENT' == err.code) {
//file did'nt exist so for example send 404 to client
} else {
//it is a server error so for example send 500 to client
}
} else {
//every thing was ok so for example you can read it and send it to client
}
} );
In case you want to serve a file using express, I would recommend to just use the sendFile error Handler of express
const app = require("express")();
const options = {};
options.root = process.cwd();
var sendFiles = function(res, files) {
res.sendFile(files.shift(), options, function(err) {
if (err) {
console.log(err);
console.log(files);
if(files.length === 0) {
res.status(err.status).end();
} else {
sendFiles(res, files)
}
} else {
console.log("Image Sent");
}
});
};
app.get("/getPictures", function(req, res, next) {
const files = [
"file-does-not-exist.jpg",
"file-does-not-exist-also.jpg",
"file-exists.jpg",
"file-does-not-exist.jpg"
];
sendFiles(res, files);
});
app.listen(8080);
If the file is not existent then it will go to the error that sends it self.
I made a github repo here https://github.com/dmastag/ex_fs/blob/master/index.js