File Select/File API - Sending files to Embedded PDFObject - javascript

So I'm trying to use file select (or file API) to select file from desktop and send it to an embedded PDF viewer in my HTML Doc. I've tried a lot of different ways with my limited knowledge to push the file from the file-api to the PDFObject and nothing seems to work. I'm not sure if it's not able to do this or if I'm just doing it wrong in many different ways.
<head>
<link href="http://pdfobject.com/css/examples.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="http://pdfobject.com/scripts/pdfobject.js"></script>
<script type="text/javascript">
window.onload = function (){
var myPDF = new PDFObject(handleFileSelect).embed();
// ORIGINALLY var myPDF = new PDFObject({ URL: "location" }).embed();
};
</script>
</head>
<body>
<div id="pdf">It appears you don't have Adobe Reader or PDF support in this web browser. Click here to download the PDF</div>
<input type="file" id="files" name="files[]" multiple />
<output id="list"></output>
<script>
function handleFileSelect(evt) {
var files = evt.target.files; // FileList object
// files is a FileList of File objects. List some properties.
var output = [];
for (var i = 0, f; f = files[i]; i++) {
output.push('<li><strong>', escape(f.name), '</strong> (', f.type || 'n/a', ') - ',
f.size, ' bytes, last modified: ',
f.lastModifiedDate ? f.lastModifiedDate.toLocaleDateString() : 'n/a',
'</li>');
}
document.getElementById('list').innerHTML = '<ul>' + output.join('') + '</ul>';
}
document.getElementById('files').addEventListener('change', handleFileSelect, false);
</script>
Can I use file select/file api to select and push a document to the PDFObject viewer or does it not allow that sort of connection?

Simply retrieve the url of the file by creating one:
url=window.URL.createObjectURL(inputFile);
and then embed the file by giving PDFObject this url:
PDFObject.embed(url, "#fileContainer");

Related

Change the entry of the pdf file to pass the exact path to it by me

I found this code which, you select a pdf file in an input, and it returns the number of pages it has. It turns out that with this way of reading pdfs is the only one I have found that reads absolutely all pdfs correctly.
What I am trying to do is to isolate the code that reads the pdf file, so that I can pass it the path to the file instead of using the input. It is to then read all the files in a folder and display the total number of pages.
But I can't figure out where exactly I would have to pass the path to the pdf file.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>PDF.js Example to Count Number of Pages inside PDF Document</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
</head>
<body>
<div class="container">
<h1 class="text-center">Count Pages inside PDF Document</h1>
<div class="form-group container">
<input type="file" accept=".pdf" required id="files" class="form-control">
</div>
<br><br>
<h1 class="text-primary container" id="result"></h1>
</div>
</body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.12.313/pdf.min.js"></script>
<script>
let inputElement = document.getElementById('files')
inputElement.onchange = function(event) {
var file = event.target.files[0];
//Step 2: Read the file using file reader
var fileReader = new FileReader();
fileReader.onload = function() {
//Step 4:turn array buffer into typed array
var typedarray = new Uint8Array(this.result);
//Step 5:pdfjs should be able to read this
const loadingTask = pdfjsLib.getDocument(typedarray);
loadingTask.promise.then(pdf => {
document.getElementById('result').innerHTML = "The number of Pages inside pdf document is " + pdf.numPages
// The document is loaded here...
});
};
//Step 3:Read the file as ArrayBuffer
fileReader.readAsArrayBuffer(file);
}
</script>
</html>
You need 2 modifications to make it work. Add "multiple" attribute to the input to allow the user to select multiple pdf files.
<input type="file" multiple accept=".pdf" required id="files" class="form-control">
And then loop through the array of files to calculated the number of pages in each:
[].forEach.call(event.target.files, file => {
Update:
Two additional changes have been added.
1. We must reset the file input at the end of the loop. Otherwise it will only work once and then stop.
// clear file selector to allow reuse
event.target.value = "";
2. We also must set the value "workerSrc" to prevent a console warning message. More details about that here.
pdfjsLib.GlobalWorkerOptions.workerSrc = '//cdnjs.cloudflare.com/ajax/libs/pdf.js/2.7.570/pdf.worker.min.js';
Run the code snippet to see how it works (hold shift key down to select multiple pdf files):
let inputElement = document.getElementById('files')
inputElement.onchange = function(event) {
[].forEach.call(event.target.files, file => {
//var file = event.target.files[i];
//Step 2: Read the file using file reader
var fileReader = new FileReader();
fileReader.onload = function() {
//Step 4:turn array buffer into typed array
var typedarray = new Uint8Array(this.result);
//Step 5:pdfjs should be able to read this
const loadingTask = pdfjsLib.getDocument(typedarray);
loadingTask.promise.then(pdf => {
document.getElementById('result').innerHTML += "<li>" + file.name + " has " + pdf.numPages + "pages</li>";
// The document is loaded here...
});
};
//Step 3:Read the file as ArrayBuffer
fileReader.readAsArrayBuffer(file);
})
// clear file selector to allow reuse
event.target.value = "";
}
// Must set worker to avoid error: Deprecated API usage: No "GlobalWorkerOptions.workerSrc" specified.
pdfjsLib.GlobalWorkerOptions.workerSrc = '//cdnjs.cloudflare.com/ajax/libs/pdf.js/2.7.570/pdf.worker.min.js';
<div class="container">
<h4 class="text-center">Count Pages inside PDF Document</h4>
<div class="form-group container">
<input type="file" multiple accept=".pdf" required id="files" class="form-control">
</div>
<br><br>
<ol class="text-primary container" id="result"></ol>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.7.570/pdf.min.js" integrity="sha512-g4FwCPWM/fZB1Eie86ZwKjOP+yBIxSBM/b2gQAiSVqCgkyvZ0XxYPDEcN2qqaKKEvK6a05+IPL1raO96RrhYDQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
You can't.
Browsers don't let you access local paths on a user's computer for security reasons.
The browser doesn't get to know that the pdf is at /home/USERNAME/confidentialdocs/file.pdf, it just gets a data blob with a given filename.

Automatically load csv/txt file from local drive into html page as table Javascript

I found a lot of good suggestions on how to load a csv/txt file into a html page into a table, but none of the solutions are working for me. Here is the code I am working with. I have both files located in my C: drive and basically would like to load this csv/txt file and show it on as a table in index.html. Thanks so much!
data.txt
heading1,heading2,heading3,heading4,heading5
value1_1,value2_1,value3_1,value4_1,value5_1
value1_2,value2_2,value3_2,value4_2,value5_2
index.html
<!DOCTYPE html>
<!-- saved from url=(0014)about:internet -->
<html lang="en">
<html>
<head>
<title>Test</title>
</head>
<body>
<script type="text/javascript">
$(document).ready(function() {
$.ajax({
type: "GET",
url: "data.txt",
dataType: "text",
success: function(data) {processData(data);}
});
});
function processData(allText) {
var allTextLines = allText.split(/\r\n|\n/);
var headers = allTextLines[0].split(',');
var lines = [];
for (var i=1; i<allTextLines.length; i++) {
var data = allTextLines[i].split(',');
if (data.length == headers.length) {
var tarr = [];
for (var j=0; j<headers.length; j++) {
tarr.push(headers[j]+":"+data[j]);
}
lines.push(tarr);
}
}
\\ alert(lines);
}
</script>
</body>
</html>
You can't access local files with JS. That would be serious security vulnerability, because you could send a malicious webpage to a user, which would download their files and send them to someone. As midrizi mentioned in the comments, you'll need a server to download files from there.
As others have noted, you can't automatically read a local file into the browser.
But you can prompt the user to select a file, using the <input type="file"> element.
Once a file has been selected via that input, it can be read via JavaScript.
<label for="file">Select a Text File:</label><br />
<input id="file" type="file" /><br/>
<button onclick="readFile()">Read File</button><br/>
let input = document.getElementById('file');
let contents = document.getElementById('contents');
function readFile () {
let file = input.files[0];
const reader = new FileReader();
reader.onload = function (evt) {
console.log('reader.onload');
contents.innerHTML = String(evt.target.result);
};
reader.readAsText(file);
}
If you can modify the data.txt a bit you can just load it as another script file without need for a server.
Change data.txt to this
var data = `heading1,heading2,heading3,heading4,heading5
value1_1,value2_1,value3_1,value4_1,value5_1
value1_2,value2_2,value3_2,value4_2,value5_2`
And load it as a javascript file before your actual script
<script type="text/javascript" src="data.txt"></script>
Then you can use the variable data which holds your file content without any ajax call.
There is no way you can retrieve a local file if you don't serve it, as pointed out in the comments to your question.
There are approaches you can take to that, though. If you can't serve it by any means, you could create a GitHub repo and upload your file there. Then you can use the link to your raw file:
And you can also take steps to automate that, but it should be easy enough committing your file locally whenever you update it and push it to GitHub. Just in case you're not familiar with Git and GitHub, here's a handy ref.
A word of caution: unless you have total control over the characters that you include in your CSV, parsing them by naively splitting commas like that might result in ugly stuff if the values within contain commas themselves. Some CSV files also come with extra stuff in the beginning of the file (like the sep indicator in the first row, which defines what character to interpret as separator). You may completely ignore these warnings if you're producing the CSV yourself.
Also I noticed your function does not take care of building the actual table, so I changed it so it does. I also used Fetch API to retrieve the data:
<!DOCTYPE html>
<!-- saved from url=(0014)about:internet -->
<html lang="en">
<html>
<head>
<title>Test</title>
</head>
<body>
<script type="text/javascript">
function processData(csv) {
let data = csv.split(/\r\n|\n/).map(v => v.split(','));
let headers = data.shift();
let table = document.createElement('table');
let thead = document.createElement('thead');
table.appendChild(thead);
thead.innerHTML = '<tr><th>' + headers.join('</th><th>') + '</th></tr>';
let tbody = document.createElement('tbody');
table.appendChild(tbody);
for (let row of data) {
tbody.innerHTML += '<tr><td>' + row.join('</td><td>') + '</td></tr>';
}
document.body.appendChild(table);
}
// I uploaded the CSV to a personal repo for this example,
// but you CAN use a local file as long as you *serve* it
fetch("https://raw.githubusercontent.com/gyohza/test/master/so/data.txt")
.then(res => res.text())
.then(text => processData(text));
</script>
</body>
</html>

Getting text from file using FileReader on Load

So, I've been working on a page that uses only local files (server is not an option, unfortunately. Not even a localhost. The struggle is real.) and I've come to a situation where I need to grab text from a .csv file and populate it to the page. I have this bit of code that works, but I need to have a file set within the function when a button is pressed. Looking up the file manually isn't an option (to visualize what I'm doing, I'm making a mock database file in the most annoying way possible (because I have to, not because I want to)).
In the page I would have something like:
<button id="myButton" onclick="getText()"></button>
<script>
var myFile = "dataset.csv";
...
</script>
The following bit of code works (in regards to having it pull the data from the csv file), but, as I said, I need to pull the text from the file when a button is pressed and just have the file name set in the script, not pulling it up manually.
<!DOCTYPE html>
<html>
<body>
<input type="file" id="fileinput" />
<div id="outputdiv"></div>
<script type="text/javascript">
function readSingleFile(evt) {
var f = evt.target.files[0];
if (f) {
var r = new FileReader();
r.onload = function(e) {
var contents = e.target.result;
var splited = contents.split(/\r\n|\n|\r|,/g);
for (i=0; i<splited.length; i++){
document.getElementById("outputdiv").innerHTML = document.getElementById("outputdiv").innerHTML + splited[i] + "<br>";
}
}
r.readAsText(f);
} else {
alert("Failed to load file");
}
}
document.getElementById('fileinput').addEventListener('change', readSingleFile, false);
</script>
</body>
</html>
From what I can tell from the API, I would need to set the file attributes to a blob in order to pass it to FileReader. How I can do this without using an input box, I have no idea. There's also a 50% chance that I am completely wrong about this since I obviously don't know how to get this done.
If someone could show me how to achieve this with regards to what I'm looking for, it would be very much appreciated. I'm absolutely stumped.
Thank you.
Note: CORS restrictons will prevent this from working in most browsers. You can use FireFox Developer Edition, which disables CORS validation.
You can use an XMLHttpRequest to load a local file:
<!DOCTYPE html>
<html>
<body>
<button onclick="readSingleFile()">Click Me</button>
<div id="outputdiv"></div>
<script type="text/javascript">
function readSingleFile() {
let xhr = new XMLHttpRequest();
let url = "relative/path/to/file.txt;
if (!url) return;
xhr.onload = dataLoaded;
xhr.onerror = _ => "There was an error loading the file.";
xhr.overrideMimeType("text/plain");
xhr.open("GET",url);
xhr.send();
}
function dataLoaded(e){
var contents = e.target.responseText;
var splited = contents.split(/\r\n|\n|\r|,/g);
for (i=0; i<splited.length; i++){
document.getElementById("outputdiv").innerHTML = document.getElementById("outputdiv").innerHTML + splited[i] + "<br>";
}
</script>
</body>
</html>

Load .txt file into webpage

I am trying to have a user click on a "load file" button to choose a file for the webpage. But I can't seem to get the actual file, just the name and when it was last modified. I need to run some JS code on that file, so I just need the actual text. I don't need to put it in the web page, but I just thought that would be a good way to display it. Here's my HTML:
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body onclick="update_loc(event)"">
<center><canvas width="400" height="400" id="myCanvas" style="border: 1px solid; border-color: #000000"></canvas></center>
<script src="./js.js"></script>
<input type="file" id="myFile">
<p id="output">YO</p>
</body>
</html>
And my JS:
var reader;
var file;
setTimeout(test_file, 500);
function test_file() {
setTimeout(test_file, 500);
file = document.getElementById("myFile").files[0];
console.log(document.getElementById("myFile").files);
reader = new FileReader();
reader.onload = function (e) {
var textArea = document.getElementById("output");
textArea.value = e.target.result;
};
reader.readAsText(file);
}
I could not figure out how to copy and paste the chrome log, but I just got the file name and time in a "FileList" object.
Try this:
<input type="file" id="files" name="files[]" multiple />
<output id="list"></output>
<script>
function handleFileSelect(evt) {
var files = evt.target.files; // FileList object
// files is a FileList of File objects. List some properties.
var output = [];
for (var i = 0, f; f = files[i]; i++) {
output.push('<li><strong>', escape(f.name), '</strong> (', f.type || 'n/a', ') - ',
f.size, ' bytes, last modified: ',
f.lastModifiedDate ? f.lastModifiedDate.toLocaleDateString() : 'n/a',
'</li>');
}
document.getElementById('list').innerHTML = '<ul>' + output.join('') + '</ul>';
}
document.getElementById('files').addEventListener('change', handleFileSelect, false);
</script>
For more info about how to read and manipulate those files (in this examples is for multiple files) check this url

JS FileReader: Read CSV from Local File & jquery-csv

I have a CSV file in the same directory as an html page, and I'd like to use FileReader to read the file contents into a jquery-csv's To Arrays function, but I can't seem to get it to work properly. I think I understand the asynchrony of this task, but have i depicted it correctly? Here, I'm trying to output the 2nd cell in the 2nd column. Thanks for any help.
<script type="text/javascript" src="https://www.google.com/jsapi?autoload={'modules':[{'name':'visualization','version':'1','packages':['timeline']}]}"></script>
<script src="https://code.jquery.com/jquery-1.9.1.min.js"></script>
<script src="jquery.csv-0.71.js"></script>
<script type="text/javascript">
var reader = new FileReader();
reader.onload = function(e) {
var text = e.target.result;
var data = $.csv.toArrays(text);
document.write(data[1][1]);
}
reader.readAsText('data.csv');
</script>
Here's a working demo provided by jquery-csv
<html>
<head>
<meta charset="utf-8" />
<title>Demo - CSV-to-Table</title>
</head>
<body>
<div id="inputs" class="clearfix">
<input type="file" id="files" name="files[]" multiple />
</div>
<hr />
<output id="list">
</output>
<hr />
<table id="contents" style="width:100%; height:400px;" border>
</table>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
<script src="http://evanplaice.github.io/jquery-csv/src/jquery.csv.min.js"></script>
<script>
$(document).ready(function() {
if(isAPIAvailable()) {
$('#files').bind('change', handleFileSelect);
}
});
function isAPIAvailable() {
// Check for the various File API support.
if (window.File && window.FileReader && window.FileList && window.Blob) {
// Great success! All the File APIs are supported.
return true;
} else {
// source: File API availability - http://caniuse.com/#feat=fileapi
// source: <output> availability - http://html5doctor.com/the-output-element/
document.writeln('The HTML5 APIs used in this form are only available in the following browsers:<br />');
// 6.0 File API & 13.0 <output>
document.writeln(' - Google Chrome: 13.0 or later<br />');
// 3.6 File API & 6.0 <output>
document.writeln(' - Mozilla Firefox: 6.0 or later<br />');
// 10.0 File API & 10.0 <output>
document.writeln(' - Internet Explorer: Not supported (partial support expected in 10.0)<br />');
// ? File API & 5.1 <output>
document.writeln(' - Safari: Not supported<br />');
// ? File API & 9.2 <output>
document.writeln(' - Opera: Not supported');
return false;
}
}
function handleFileSelect(evt) {
var files = evt.target.files; // FileList object
var file = files[0];
// read the file metadata
var output = ''
output += '<span style="font-weight:bold;">' + escape(file.name) + '</span><br />\n';
output += ' - FileType: ' + (file.type || 'n/a') + '<br />\n';
output += ' - FileSize: ' + file.size + ' bytes<br />\n';
output += ' - LastModified: ' + (file.lastModifiedDate ? file.lastModifiedDate.toLocaleDateString() : 'n/a') + '<br />\n';
// read the file contents
printTable(file);
// post the results
$('#list').append(output);
}
function printTable(file) {
var reader = new FileReader();
reader.readAsText(file);
reader.onload = function(event){
var csv = event.target.result;
var data = $.csv.toArrays(csv);
var html = '';
for(var row in data) {
html += '<tr>\r\n';
for(var item in data[row]) {
html += '<td>' + data[row][item] + '</td>\r\n';
}
html += '</tr>\r\n';
}
$('#contents').html(html);
};
reader.onerror = function(){ alert('Unable to read ' + file.fileName); };
}
</script>
</body>
</html>
Disclaimer: I'm the author of jquery-csv
It's not going to work.You have no permissions to read files with javascript from the browser. The only way to deal with it is to create an input[type=file] tag and add onChange event to it. For example:
document.getElementById('fileupload').addEventListener('change', function (e) {
var files = e.target.files;
//proceed your files here
reader.readAsText(files[0]);
}, false);

Categories