I'm generating a PDF using the PDFKit library and I would like to insert the generated PDF into a MongoDB collection. On the client side a user should be able to see the list of files in the collection and choose one of these files to download.
As of now I'm saving the PDF in the collection as a Uint8Array and I can then click on the file at the front end to download it.
However, my problem is that the file seems to be corrupt. It will not open in Adobe Reader or in Chrome.
I've tried saving it to the collection with and without PDFKits compression.
Is this possible to do? Or do I have a bad approach to this.
Any help with this would be great and thanks in advance!
Server Side
Most of the code here is based off of this post on the PDFKit GitHub
var doc = new PDFDocument();
var stream = require('stream');
var converter = new stream.PassThrough();
doc.pipe(converter);
var data = [];
converter.on('data', function(chunk) {
data.push(chunk);
});
converter.on('end', Meteor.bindEnvironment( function () {
var buffer = Buffer.concat(data);
PdfFiles.insert({ data:buffer, userID:userId });
}));
// Adding content to the PDF
doc.end();
Client Side
'click .downloadPDF': function (event) {
event.preventDefault();
var file = UserFiles.findOne({userID:Meteor.userId()});
var FileSaver = require('file-saver');
var blob = new Blob(file.data, {type: "application/pdf"});
FileSaver.saveAs(blob, "AwesomePDF");
}
I got the code to work as intended simply by changing:
var blob = new Blob(file.data, {type: "application/pdf"});
to
var blob = new Blob([file.data], {type: "application/pdf"});
Related
I have a very simple application I am making that needs to load 30 second m4a files from a couch server. I am able to receive the files but can not get them to load in a player. The files are uploaded through Fauxton and have been deleted and reuploaded to be sure the issue was not in the upload.
I have also loaded the object url into a link and tried to download the file which can not be played.
I have tried both using the source directly in the audio tag as well as adding the source tag.
I have tested the files in the audio player and they work fine locally.
I think I there is something wrong with the way I am creating the blob or url.
<audio controls id="mediaPlayer"></audio>
var db = new PouchDB('http://user:password#localhost:5984/music');
db.get('9d3f17d01be8283c461eaa01940329b4', { attachments:true } ).then(function (doc){
// Load first file
var media = Object.values(doc._attachments)[0];
// Get Player
var player = document.getElementById('mediaPlayer');
// Create blob from data - media content type is
var blob = new Blob([ media.data ], { type: media.content_type });
// Create url from blob
var afile = URL.createObjectURL(blob);
// Set source and load
player.src = afile;
player.load();
});
I solved my own issue. This was a complete oversight on my end. Fauxton uploads all attachments as Base64 not blobs. I had to simply decode the data before converting it to a blob. I am using node so I used buffer to decode the string before creating the blob.
If you are using raw vanilla js you should be able to use atob(media.data) in place of the buffer, but I did not test it.
import { Buffer } from 'buffer';
var db = new PouchDB('http://user:password#localhost:5984/music');
db.get('9d3f17d01be8283c461eaa01940329b4', { attachments:true } ).then(function (doc){
// Load first file
var media = Object.values(doc._attachments)[0];
// Get Player
var player = document.getElementById('mediaPlayer');
// Remove Encoding
var raw = Buffer.from(media.data, 'base64');
// Create blob from data
var blob = new Blob([ raw ], { type: media.content_type });
// Create url from blob
var afile = URL.createObjectURL(blob);
// Set source and load
player.src = afile;
player.load();
});
I'm using the management API to get all my installed apps and extensions. I want to send this information to server.
Every app/extension has an icon array, that has size and url.
The url is something like chrome://extension-icon/gmgpodcgeocidkeclglljo88jp9kclhhmmdacfo/32/0. I want to send it to my server in base64.
What I'm trying to do is something like:
var reader = new FileReader();
reader.onloadend = function() {
result = reader.result;
}
if (file) {
reader.readAsDataURL(file);
} else {
result = "";
}
Where file is a File object of the icon url. But I cannot find how to create an File object with this url format.
I've tried:
var fileUrlArray = ["chrome://extension-icon/gmgpodcgeocidkeclglljo88jp9kclhhmmdacfo/32/0"];
var file = new File(fileUrlArray, 'icon.png');
And as a result I got an absolutely wrong base64 string.
Any ideas about how to do it?
Thanks.
I am currently a developing an application that is using a PDFTron webviewer. Is there anyway to save the edited pdf edited with pdftron webviewer to the server?
There is a feature of pdftron that saves annotations to the server, but I need to save the whole pdf with the edits to the server.
You could call the following function from a WebViewer config file to get the PDF data as a blob. Once you have the blob you can refer to one of the many examples online of how to upload a blob to a server.
function uploadPDF() {
var docViewer = readerControl.docViewer;
var options = {
xfdfString: docViewer.getAnnotationManager().exportAnnotations()
};
var doc = docViewer.getDocument();
doc.getFileData(options).then(function(data) {
var arr = new Uint8Array(data);
var blob = new Blob([arr], {
type: 'application/pdf'
});
// upload blob here
});
}
the following code downloads a file that can't be opened(corrupt) and I have absolutely no idea why. I've tried this in so many ways but it never works, it always produces a corrupt file. The original file isn't the problem because it opens fine. I'm trying to open mp4, mp3, and image files.
//$scope.fileContents is a string
$scope.fileContents = $scope.fileContents.join(",");
var blob = new Blob([$scope.fileContents], {type: $scope.file.fileDetails.type});
var dlURL = window.URL.createObjectURL(blob);
document.getElementById("downloadFile").href = dlURL;
document.getElementById("downloadFile").download = $scope.file.fileDetails.name;
document.getElementById("downloadFile").click();
window.URL.revokeObjectURL(dlURL);
You need to download the file contents as binary using an ArrayBuffer e.g.
$http.get(yourFileUrl, { responseType: 'arraybuffer' })
.then(function (response) {
var blob = new Blob([response.data], {type: $scope.file.fileDetails.type});
// etc...
});
Sources:
angular solution
plain javascript solution
Trying to create image(screenshot) of a HTML page using javascript. Able to generate the html blob and display the same in new tab as read only HTML page using the below code.
var scr = document.documentElement.cloneNode(true);
var blob = new Blob([scr.outerHTML], {type: 'text/html'});
window.open(window.URL.createObjectURL(blob));
Please anyone could tell me how to save the same as image.
Take a look at FileSaver.js,
var bb = new BlobBuilder();
bb.append((new XMLSerializer).serializeToString(document));
var blob = bb.getBlob("application/xhtml+xml;charset=" + document.characterSet);
saveAs(blob, "document.xhtml");
Some Documentation
API