How to make a pdf from MongoBD Binary with File API? - javascript

I would like some help to make a File object from a pdf stored in MongoDB.
I am not using GridFS, the file is stored as such:
File structure in MongoDB
I am using this function to make the File:
const handlegetfile = () => {
API.getFile(2).then((result) => {
console.log(result.data);
const file = new File(Uint8Array.from(result.data.File.data), result.data.File.name);
console.log(file);
API.writeFile({
CodeTiers: "2525",
Type: { value: "non", label: "testfile" },
Format: "pdf",
File: file,
});
});
};
The .pdf file created by the writeFile() function can't be opened, and when opened with an editor, it looks like this:
pdf data after retrieved
Important: I do not want to write the file to the disk, writeFile() is just here to be sure that the pdf can be opened.
The thing is: the data goes from this in the original file:
original pdf data
To this in MongoDB:
data in MongoDB
To what is in the second screenshot. I am pretty sure the problem comes from the cast to a Uint8array but I can't find what else to use there for it to work. I tried exploding the response with {...result.data.File} and using an ArrayBuffer, also by simply casting to an array new File([result.data.File.data], result.data.File.name) but I couldn't get it to work either way.
Could you help me please ?

Related

How to compare two OpenAPI JSON files using JavaScript?

I download an OpenAPI file from localhost and convert it to .json. It becomes something like this:
"components":{"responses":{"r200":{"content":{"application/json":{"schema":{"properties" ....
I'm doing this using this JavaScript code:
const processData = async () => {
const req = await axios.get('http://localhost:5004/swagger');
let reqJson = JSON.stringify(req.data);
fs.writeFile('swagger.json', reqJson, (err) => {
if (err) throw err;
})
}
processData()
If there are any changes in the OpenAPI file on localhost, I want to download it, convert to .json, save it as a new file and compare with the original swagger.json. It will be the same to previous code, but
fs.writeFile('newSwagger.txt' ....
And changes has to be in error field in url.
Question: How can I compare these files, and show any changes in a popup on a web site like:
Attention: there is changes in Backend API:
Missing api/xxx/yyy
Added api/zzz/yyy

How do I display a PDF I retrieved from a server onto a PDF.js custom pdf viewer page?

I have a pdf sitting in my cshtml page via #Html.HiddenFor(m => m.ConstructedLinkToPdfDocumentForPDFJS) that I need to pass to a javascript file. This javascript file is using PDF.js to display that PDF on a custom pdf viewer I made for my website. I have it passed as a hiddenfor just to try to do it from a server that I made solely for storing this pdf and retrieving it. I am constructing a string link in a C# file on my server that links to a pdf file that is stored on said server. It fully constructs the string to that pdf file, and passes it up to my model to be seen by Javascript, but somehow in Javascript the string ends up as undefined from the following code:
var fullLink;
const initialState =
{
pdfDoc: null,
currentPage: 1,
pageCount: 0,
zoom: 1,
};
//On load
$(document).ready(function () {
fullLink = document.getElementById('#ConstructedLinkToPdfDocumentForPDFJS');
});
//Load pdf document
pdfjsLib
.getDocument(fullLink)
.promise.then((data) => {
initialState.pdfDoc = data;
console.log('pdfDocument', initialState.pdfDoc);
pageCount.textContent = initialState.pdfDoc.numPages;
renderPage();
})
.catch((err) => {
alert(err.message);
});
Should I not be using document.getElementById() and instead use something else?

Create File object without saving

I'm trying to look for a way to create a .txt File object without saving it to disk in Node.js. In browser I'd do something like
new File(['file_contents'], 'file_name.txt', {type: 'text/plain'})
The end aim is to create a .txt file object temporarily for my Discord Bot to send as a message attachment.
From the discord.js documentation, I presume I'm supposed to create a Buffer or Stream object representing the file.
I'm already using require('node-fetch') library to read attachments in messages, if that has any relevancy (but can't see anything in their docs on this either).
After playing around in console I've found Buffer.from('string of txt file contents') to represent the file seems to work fine.
Usage:
channel.send(new Discord.MessageAttachment(Buffer.from('Hello World'), 'file_name.txt'))
In order to write a text file in JS you should use the fs library, included in Node.js.
Here is an example of writing to a file:
fs = require('fs');
let content = "Hello world!";
fs.writeFile('file.txt', content, function (err) {
if (err) return console.log(err);
// Code here will execute if successfully written
});
Then in order to send a local file to Discord you can use .send with an object containing a files property in it, like this:
channel.send({
files: [{
attachment: 'entire/path/to/file.txt',
name: 'file.txt'
}]
}).then(() => {
// Delete file
fs.unlink('file.txt');
});
You can see more about .send() here and you can find more about the fs module here

Issue while printing pdf files from Blob angular

I have an Api that returns the data in the format of
{ fileName: string, blob: Blob }[]
I want to print all these files, so I am using
_files.forEach((_fileInfo) => {
const blobUrl = URL.createObjectURL(_fileInfo.blob);
const oWindow = window.open(blobUrl, "print");
oWindow.print();
oWindow.close();
});
this opens the multiple print windows, but in preview it shows blank documents.
but when i download all these files as a zip it downloads the correct PDF files.
// add files to zip
files.forEach((_fileInfo) => {
zip.file(_fileInfo.fileName, _fileInfo.blob);
});
// download and save
return zip.generateAsync({ type: "blob" }).then((content) => {
if (content) {
return saveAs(content, name);
}
});
What could be the issue,
is there any way to print all documents in a sequence without opening multiple windows?
Pdf file takes time to load thats why it was showing blank document, So i used print-js to solve this issue.
how to import
import * as printJS from "print-js";
how to use
const blobUrl = URL.createObjectURL(_fileInfo.blob);
printJS(blobUrl);
In case, you don't want to use printJS
I was facing the same issue but in my case I only have to deal with one file at a time. I solved it by putting the print function in a timeout block, so in your case this would be
setTimeout(function(){
oWindow.print();
}, 1000)
if this works then great, if not then you might also need to set the source of window equal to the 'blobUrl' that you created. This should be done after you come out of the loop.

Download files from server using Meteor.js

Here is my workflow as of now:
In a button click event, I have search results being exported to a .csv file, which is saved to the server. Once the file is saved, I want to send it for download to the browser. Using this question How to handle conditional file downloads in meteor.js, I created a method that is called after the method that saves the file returns. Here is that method:
exportFiles: function(file_to_export) {
console.log("to export = "+file_to_export);
Meteor.Router.add('/export', 'GET', function() {
console.log('send '+file_to_export+' to browser');
return [200,
{
'Content-type': 'text/plain',
'Content-Disposition': "attachment; filename=" + this.request.query.file
}, fs.readFileSync( save_path + this.request.query.file )];
});
}
My question, however, is how to invoke that route? Using .Router.to('/export?file=filename.ext') doesn't work, and causes the user to leave the current page. I want this to appear seamless to the user, and I don't want them to have any idea they are being redirected. Before anyone asks, save_path is declared outside of the method, so it does exist.
I have gotten it! However, it required the use of a few additional packages. First, let me describe the workflow a little more clearly:
A user on our site performs a search. On the subsequent search results page, a button exists that allows the user to export his/her search results to a .csv file. The file is then to be exported to the browser for download.
One concern we had was if a file is written to the server, making sure only the user who is exporting the file has the ability to view the file. To control who had visibility on files, I used a meteorite package, CollectionFS (mrt add collectionFS or clone from github). This package writes file buffers to a mongo collection. Supplying an "owner" field when saving gives you control over access.
Regardless of how the file is created, whether saved to the server via an upload form or generated on the fly the way I did using the json2csv package, the file must be streamed to CollectionFS as a buffer.
var userId = Meteor.userId()
var buffer = Buffer(csv.length); //csv is a var holding the data for write
var filename = "name_of_file.csv";
for ( var i=0; i<csv.length; i++ ) {
buffer[i] = csv.charCodeAt(i);
}
CollectionFS.storeBuffer(filename, buffer, {
contentType: 'text/plain',
owner: userId
});
So at this point, I have taken my data file, and streamed it as a buffer into the mongo collection. Because my data exists in memory in the var csv, I stream it as a buffer by looping through each character. If this were a file saved on a physical disk, I would use fs.readFileSync(file) and send the returned buffer to CollectionFS.storeBuffer().
Now that the file is saved as a buffer in mongo with an owner, I can limit through way I publish the CollectionFS collection who can download/update/delete the file or even know the file exists.
In order to read the file from mongo and send the file to the browser for download, another Javascript library is necessary: FileSaver (github).
Using the retrieveBlob method from CollectionFS, pull your file out of mongo as a blob by supplying the _id that references the file in your mongo collection. FileSaver has a method, saveAs that accepts a blob, and exports to the browser for download as a specified file name.
var file = // file object stored in meteor
CollectionFS.retrieveBlob(file._id, function(fileItem) {
if ( fileItem.blob ) saveAs(fileItem.blob, file.filename);
else if ( fileItem.file ) saveAs(fileItem.file, file.filename);
});
I hope someone will find this useful!
If your route works, when when your method returns you could open a new window containing the link to the text file.
You've already added in content disposition headers so the file should always ask to be saved.
Even if you just redirect to the file, because it has these content disposition headers it will ask to be saved and not interrupt your session.

Categories