I'm very new to pdf.js and am probably making some basic mistake. I'm trying to just copy the "Hello World with document load error handling" example provided here:
https://mozilla.github.io/pdf.js/examples/
I just copy and pasted the code across to new html, css and js files but didn't work. I tried changing the url in pdfjsLib.getDocument(url) to a local file directory on my computer i.e. ./pdf/test.pdf but didn't work. I tried changing the
<script src="//mozilla.github.io/pdf.js/build/pdf.js"></script>
to
<script src="https://cdn.jsdelivr.net/npm/pdfjs-dist#2.2.228/build/pdf.min.js"></script>
but that didn't work either.
My console log states two things:
1) Loading failed for the with source “file:///pdf.js/build/pdf.js”
2) TypeError: pdfjsLib is undefined
I understand I am a beginner here but would it be too much to ask the guys who put so much effort into creating it to write a few lines about how to use it for beginners like me? Anyways, if someone can help solve my what I'm sure is a very basic question, it would be much appreciated.
Thanks
Most of these problems are caused by the fact that you are running your test by opening an html file, thus the browser use the file:// instead of http:// or https://.
A quick "hack" to fix the problem in you situation is to insert the <base href="https://mozilla.github.io"> (HTML base tag) inside the head of your test html file (I used the given example as it is, with no changes inside a blank html document) so that you fool the browser and make it search on the Github for the files.
The "correct" way to test such codes and libraries is to install a local web-server and serve the files from there (usually as http://localhost).
An example of the test I created:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Test</title>
<meta name="description" content="Testing pdf.js">
<meta name="author" content="GramThanos">
<!-- hack code -->
<base href="https://mozilla.github.io">
</head>
<body>
<script src="//mozilla.github.io/pdf.js/build/pdf.js"></script>
<h1>PDF.js 'Hello, world!' example</h1>
<canvas id="the-canvas"></canvas>
<script type="text/javascript">
// If absolute URL from the remote server is provided, configure the CORS
// header on that server.
var url = 'https://raw.githubusercontent.com/mozilla/pdf.js/ba2edeae/examples/learning/helloworld.pdf';
// Loaded via <script> tag, create shortcut to access PDF.js exports.
var pdfjsLib = window['pdfjs-dist/build/pdf'];
// The workerSrc property shall be specified.
pdfjsLib.GlobalWorkerOptions.workerSrc = '//mozilla.github.io/pdf.js/build/pdf.worker.js';
// Asynchronous download of PDF
var loadingTask = pdfjsLib.getDocument(url);
loadingTask.promise.then(function(pdf) {
console.log('PDF loaded');
// Fetch the first page
var pageNumber = 1;
pdf.getPage(pageNumber).then(function(page) {
console.log('Page loaded');
var scale = 1.5;
var viewport = page.getViewport({scale: scale});
// Prepare canvas using PDF page dimensions
var canvas = document.getElementById('the-canvas');
var context = canvas.getContext('2d');
canvas.height = viewport.height;
canvas.width = viewport.width;
// Render PDF page into canvas context
var renderContext = {
canvasContext: context,
viewport: viewport
};
var renderTask = page.render(renderContext);
renderTask.promise.then(function () {
console.log('Page rendered');
});
});
}, function (reason) {
// PDF loading error
console.error(reason);
});
</script>
</body>
</html>
Related
I am using wix and in order to customize any html you need to use an embed object which creates a sandboxed iframe on the site. I have a decent grasp of how this works and posting messages to it but what I am having difficulties with is generating a pdf into this iframe.
I have done some reading and I think I get the overall concept. While traditionally you would just set the source to some document on a server somewhere I am generating the content dynamically based on user action. So it looks like something like pdfkit and creating a blob is the way to go.
I think I am able to generate the pdf without issues as well as a blob url no problem
[![console image][1]][1]
I can manually open the console and get that URL and paste it in the browser and the document opens exactly how I expect it. However I can't get it to display normally in the browser.
I have tried setting the src of various elements = to the blob url without luck.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
blah
<script src="https://github.com/foliojs/pdfkit/releases/download/v0.11.0/pdfkit.standalone.js"></script>
<script src="https://github.com/devongovett/blob-stream/releases/download/v0.1.3/blob-stream.js">
</script>
</head>
<body>
<script>
const doc = new PDFDocument
const stream = doc.pipe(blobStream())
doc.fontSize(25).text('Testing document', 100, 80);
console.log(doc);
doc.end();
stream.on('finish', function() {
window.src = stream.toBlobURL('application/pdf');
const a = document.createElement('a');
a.href = stream.toBlobURL('application/pdf');
a.download = 'ShoppingList' || 'download';
console.log("download IS",a)
});
</script>
</body>
</html>
In addition to setting the window.src I have tried document.src iframe.src which returns an error.
displaying isn't strictly necessary but a download link would be. Is there some other way I can do this to get this data? I feel I am missing something very simple.
I have had to change the examples as given on [http://pdfkit.org/docs/getting_started.html][2] but I don't think this is any issue as the package is working as expected and the document is being created.
Edit:
I have made some progress on this but am getting stuck in downloading it. What I did was these 2 things.
<input type="button" id = "dload" onclick="location.href='';" value="Download Shopping List" />
document.getElementById("dload").onclick = function(){location.href = stream.toBlobURL('application/pdf')};
the pdf actually shows in the iframe as expected with the full capabilities of a pdf preview however the download doesn't work at all it just says failed - network error and the filetype is not a pdf which makes sense. Is there something else I can add to get this working?
Edit2: Tried one more thing that doesn't work very well since popups are mostly blocked
window.open(stream.toBlobURL('application/pdf'), '_blank');
this, while it technically works is really messy and is causing a number of problems. Also it works differently on mobile vs desktop. There has to be some simple way to just show a pdf but it seems to just result in more questions the more I search.
[1]: https://i.stack.imgur.com/le6o9.png
[2]: http://pdfkit.org/docs/getting_started.html
I have partially solved my question and it is good enough for what I need. Here is what I did.
<html>
<head>
<script src="https://github.com/foliojs/pdfkit/releases/download/v0.11.0/pdfkit.standalone.js"></script>
<script src="https://github.com/devongovett/blob-stream/releases/download/v0.1.3/blob-stream.js"></script>
<script type="text/javascript">
window.onmessage = (event) => {
if (event.data) {
// create a document and pipe to a blob
var doc = new PDFDocument();
var stream = doc.pipe(blobStream());
doc.font('Helvetica');
doc.fontSize(20);
doc.text('Some Text',200,20);
// end and display the document in the iframe to the right
doc.end();
stream.on('finish', function() {
const blob = stream.toBlob('application/pdf')
const a = document.createElement('a');
a.href = window.URL.createObjectURL(blob);
a.download = "YourFileName";
a.style.position = 'fixed';
a.target = '_blank';
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
});
};
};
</script>
</head>
<body>
</body>
</html>
while I can't see the pdf using this method it does download correctly which was the more important piece. Technically I could combine the two but since the download button on the iframe doesn't work I think it would be confusing for someone having a separate button to actually download it. So I have a separate button outside the frame that triggers the "onmessage" it is a function of wix. This triggers all document generation and download.
Is it possible to get a dataUrl (or simply the SVG source code) of an SVG image which is not inline SVG, but an external SVG file on the same domain?
I had a look at https://github.com/sampumon/SVG.toDataURL, but it only works for inline SVG, not for external SVG files.
To be clear, I am not looking to convert the SVG image to a PNG and then get the PNG's dataUrl, I need to get at the actual SVG code.
The solution would need to be open source and work in most modern browsers.
Here's a minimal version of what I'm trying to do:
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript">
function getSvgDataUrl(imgID) {
// FIXME!!!
return dataUrl;
}
function doTheThing() {
result = getSvgDataUrl('foo');
console.write(result);
}
</script>
</head>
<body onload='doTheThing()'>
<img src='myImage.svg' id='foo'>
</body>
</html>
I think the obvious thing to do here is to put the SVG image on a canvas and then get a dataURL from the canvas, like this:
source = new Image();
source.src = 'myImage.svg';
source.onload = function(event){
c = document.getElementById('canvas');
ctx = c.getContext('2d');
ctx.drawImage(source,0,0,116,23);
data = c.toDataURL('image/svg', 1.0);
alert(data);
};
But this gives me a PNG dataURL, not SVG.
I also looked at XMLSerializer, which seemed promising, but I can't work out how to get at the internal SVG. Doing this:
svgImg = document.getElementById('foo');
s = new XMLSerializer();
console.log(s.serializeToString(svgImg));
Just gives the following console output:
<img xmlns="http://www.w3.org/1999/xhtml" src="myImage.svg" id="foo" />
Justin Taddei gave the answer: it's fetch. I get the feeling it was dumb of me not to know this but on the other hand I bet I'm not the only one to get confused by this, so here's the code that worked:
async function getText(file) {
let x = await fetch(file);
let y = await x.text();
console.log(y);
}
getText("myImage.svg");
There's info about fetch here: https://www.w3schools.com/js/js_api_fetch.asp
I've run into an error that a lot of people seem to have gotten in the past but the explanations are not clear to me. After using the .getImageData() method in my javascript to get the pixel data of a picture that I have stored on my computer and inputed into an img tag in my HTML webpage I get the SecurityError: DOM Exception 18.
I'm simply running an HTMl file in my browser and it is preventing me from getting this stuff done. I've read about making a proxy to get around it or something or hosting the image on my own domain. I don't exactly understand what this means or how to go about doing it. So, it'd be greatly appreciated if anyone could help. I'll input my code here and leave a link to the image as well.
http://i.imgur.com/8UzWlWX.png
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Test</title>
<script>
function putimg() {
var img = document.getElementById('img');
var can = document.getElementById('C');
var ctx = can.getContext('2d');
ctx.drawImage(img, 0, 0);
var position = [];
var imgdata = ctx.getImageData(0,0, img.width, img.height);
var data = imgdata.data;
for (var i = 0; i < data.length; i += 4) {
if (data[i] == 255) {
var vertical = Math.floor((data.indexOf(data[i]) / 4) / 400);
var horizontal = Math.floor((data.indexOf(data[i]) / 4) % 400);
position.push(horizontal, vertical);
}
}
}
ctx.putImageData(imgdata, 0, 0);
}
</script>
</head>
<body onload="putimg()">
<h1>Test</h1>
<img id="img" src="circle-image-alone.png" style="display:none"></img>
<canvas id="C" width="600" height="600"></canvas>
</body>
</html>
EDIT: the file is now in the same folder as the html file, but the same error flag appears
The problem is that this is breaking Same-origin policy. You need to either have imgur relax their Cross-origin sharing or host the image yourself.
If you are running the HTML file directly from the file system on your computer then you can just download the image to the same folder as your html file is in, and reference it like
<img id="img" src="8UzWlWX.png" style="display:none"></img>
Here are the hoops you need to jump through to make it work through a foreign origin like imgur: https://developer.mozilla.org/en-US/docs/HTML/CORS_Enabled_Image
As you've discovered, your browser considers even your local file system to be a different domain.
So you’re still violating cross-domain even if your image and .html are in the same local directory.
You need a CORS compliant way of loading your image.
Here’s how:
Open up an account on dropbox.com and host your image there.
Be sure to put your image in the “public” folder they set up for you.
They allow cross-domain downloading of their images from your “public” folder.
To get the URL of your dropbox image:
Right-click the image in your public folder and select “copy public link”.
This will put the url into your clipboard where you can paste it into your code.
Then use this code to download your image into the browser in a CORS compliant way:
// download an image from dropbox.com
// in a CORS compliant way
var img=new Image();
img.onload=function(){
ctx.drawImage(img, 0, 0);
}
img.crossOrigin="anonymous";
img.src="dropbox.com/yourDropboxAccount/yourImage.png";
The result is an image that you can fully examine/change/save with:
ctx.getImageData
ctx.putImageData
ctx.toDataURL.
I've web app running. And it uses ajax upload. The issue is recently users are uploading too big images. So it's taking a bit more time. Users are complaining about that. So what I was thinking is this, 'If I somehow crop and resize the image via js and then send it to the server via ajax upload then the time will be reduced'. So is there any way to do that? Any idea for it?
A solution is to use modern ways like FileReader and Canvas (But this works only on the latest modern browsers).
http://caniuse.com/filereader
http://caniuse.com/canvas
In this example i show how to let the client resize an image before uploading by setting a max width & height mantaining aspect ratio.
In this example max widthHeight = 64;
your final image is c.toDataURL();
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script>
var h=function(e){
var fr=new FileReader();
fr.onload=function(e){
var img=new Image();
img.onload=function(){
var MAXWidthHeight=64;
var r=MAXWidthHeight/Math.max(this.width,this.height),
w=Math.round(this.width*r),
h=Math.round(this.height*r),
c=document.createElement("canvas");
c.width=w;c.height=h;
c.getContext("2d").drawImage(this,0,0,w,h);
this.src=c.toDataURL();
document.body.appendChild(this);
}
img.src=e.target.result;
}
fr.readAsDataURL(e.target.files[0]);
}
window.onload=function(){
document.getElementById('f').addEventListener('change',h,false);
}
</script>
</head>
<body>
<input type="file" id="f">
</body>
</html>
In the canvas part of the code you can also add a cropping function.
Edit as asked in the comments
c.toDataURL();
is the image base64_string you can store it in a hidden input,append to a new FormData() or wherever you want.
on the server
$data=explode(',',$base64_string);
$image=base64_decode($data[1]);
write to file
$f=fopen($fileName,"wb");
fwrite($f,$image);
fclose($f);
or
$gd=imagecreatefromstring($image);
you can also store the whole base64 image string in the database and always use that.
I create a web page and put an img tag on this page. the img.src is the url of the image from the network IP camera. It works but the stream I get have delays. I understand this delay is because I load the image and loading image takes some time. my question is how can I minize these delay. I do the following;
<script language="Javascript">
x = document.getElementById("stream");
intervalID = setInterval(LoadImage, 0);
function LoadImage()
{
x = document.getElementById("stream");
x.src = "http://IP:PORT/jpg/image.jpg";
}
</script>
<img id="stream"
width="640" height="480"
alt="Press reload if no video displays"
border="0" style="cursor:crosshair; border:medium; border:thick" />
<button type="button" id="btnStartLive" onclick="onStartLiveBtnClick()">Start Live</button>
I've just found your question in the unanswered section and decided to give it a go. The following script creates an internal <img> tag (with new Image()), assigns the necessary attributes, then sets an onload "event handler" attribute, which checks when the image loaded. When that function is called, the #stream is replaced by the new internal image tag.
In case the #stream is not directly inside the body tag (i.e. inside another element like a <div>), edit streamParentElement to point to the image's parent element.
I added a ?nocache query parameter to the string, because while I was testing the code, I found out that the image tag was changing but the visible image stayed the same. I also added a loadDelay, because the images on my client were loading too fast, and it got to the point where it crashed my browser. I advise you to not lower that value below 50. Live demonstration of this code here
<script language="Javascript">
var streamParentElement = document.body, loadDelay = 200;
setTimeout(MakeImage,1);
function MakeImage(){
var img = new Image();
img.src = "http://IP:PORT/jpg/image.jpg?nocahce="+new Date().getTime()+Math.random();
img.width = 640;
img.height = 480;
img.style.border = 0;
img.style.cursor = 'crosshair';
img.id = 'stream';
img.onload = function(){
var stream = document.getElementById("stream");
streamParentElement.insertBefore(img,stream);
stream.outerHTML = '';
setTimeout(MakeImage, loadDelay);
};
}
</script>
<img id="stream" alt="Press reload if no video displays" />
create your html page. eg:
<html>
<head>
<title>
Some Page
</title>
</link rel="stylesheet" href="path to your css file"/>
<script type="text/javascript" src="path to you javasctipt file"></script>
</head>
<body>
<h1 onClick="javascript:someFunction()">
Click here
</h1>
</body>
</html>
you can then create many other "someFunction" functions. They all just reference the AJAX function.this is just to make typing a little less...
The easiest ajax way:
var path;
var div;
var xmlhttp = new XMLHttpRequest();
function someFunction()
{
path = "path to another html file";
div = "the name of the div tag's content you want to change eg. content";
AJAX(path, div);
}
function AJAX(path, div)
{
xmlhttp.open("GET", path, false);
xmlhttp.send();
if (xmlhttp.readyState == 4)
{
document.getElementById(div).innerHTML = xmlhttp.responseText;
}
}
now just include the image in the html file.
ajax allows you to change just the content of the div you gave it, without reloading the whole page.
I would try putting your images into photoshop and making the resolution 72 or less. Also if you save the images as a GIFs they should be much smaller.
maybe handle the image loading in an outside script that runs faster than a web page refreshes, then embed it? like a "videoloader.js" so that it can load separately and not have to wait on the html page to load.
<script src="videoloader.js"></script>
you could also convert the images shown on the fly into lesser quality jpgs using javascript
see if this helps:
Load lower quality image if higher one inst available