How to store and retrieve image to localStorage? - javascript

Thought I had this, but no. The goal: snap a photo (insurance card), save it locally, and retrieve it later.
// Get a reference to the image element
var elephant = document.getElementById("SnapIt_mobileimage_5");
var imgCanvas = document.createElement("canvas"),
imgContext = imgCanvas.getContext("2d");
// Make sure canvas is as big as the picture
imgCanvas.width = elephant.width;
imgCanvas.height = elephant.height;
// Draw image into canvas element
imgContext.drawImage(elephant, 0, 0, elephant.width, elephant.height );
console.log( 'Did that' );
// Get canvas contents as a data URL
var imgAsDataURL = imgCanvas.toDataURL("data:image/jpg;base64,");
// Save image into localStorage
try {
localStorage.setItem("elephant", imgAsDataURL);
}
catch (e) {
console.log("Storage failed: " + e);
};
//Did it work?
var pic = localStorage.getItem("elephant");
console.log( elephant );
console.log( pic );
Each step succeeds, the final output is:
<img id="SnapIt_mobileimage_5" class=" SnapIt_mobileimage_5" name="mobileimage_5" dsid="mobileimage_5" src="files/views/assets/image/IMG_0590.JPG">
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgA
On a new page, when I ask
var policy_shot = localStorage.getItem( 'elephant' );
console.log( policy_shot );
$('#TestScreen_mobileimage_1').src = policy_shot ;
It logs the binary:
data:image/png;base64,iVBORw0KGgoAAAANSUhEUg ....
But the image doesn't appear.
Is there a simpler approach?
Why is the getItem (binary) preceded by data:image/png; instead of data:image/jpg ?
Is that why it doesn't display, or am I doing something else wrong?

1) This is the only way you can convert an image into a string locally (with the excpetion of files loaded with FileReader, see below). Optionally you need to use the server to do it.
2) To get a JPEG image you need to use the argument like this:
var datauri = imgCanvas.toDataURL("image/jpeg", 0.5); //0.5 = optional quality
don't use data:... in the argument as that will be invalid and it will produce the default PNG as you can see in your result. toDataURL() can only take a type, ie. image/png, image/jpeg etc.
3)
External files
If your image was loaded from a different origin (scheme, server ...) or by using local referenced files (file://, /my/path/ etc.) CORS kicks in and will prevent you from creating a data-uri, that is: the image will be empty (and therefor invisible).
For external servers you can request permission to use the image from a cross-origin by supplying the crossOrigin property:
<img src="http://extrernalserver/...." crossOrigin="anonymous" />
or by code (img.crossOrigin = 'anonymous';) before setting the src.
It's however up to the server to allow or deny the request.
If it still doesn't work you will need to load your image through a proxy (f.ex. a page on your server that can load and the image externally and serve it from your own server).
Or if you have access to the server's configuration you can add special access allow headers (Access-Control-Allow-Origin: *, see link below for more details).
CORS (Cross-Origin Resource Sharing) is a security mechanism and can't be worked around other than these ways.
Local files
For local files you will need to use FileReader - this can turn out to be an advantage as FileReader comes with a handy method: readAsDataURL(). This allow you to "upload" the image file directly as a data-uri without going by canvas.
See examples here:
https://developer.mozilla.org/en-US/docs/Web/API/FileReader
Unfortunately you can't just pick the files from code - you will need to provide an input element or a drop zone so the user can pick the files (s)he want to store.
Conclusion
If all these steps are fulfilled to the degree that you actually do get an image the problem possibly is in the other end, the string being truncated being too long to store.
You can verify by checking the length before and after storing the string to see if it has been cut:
console.log(imgAsDataURL.length);
... set / get ...
console.log(pic.length);
Other possibilities:
The image element is not properly defined.
A bug in the browser
A bug in the framework
(I think I covered most of the typical pitfalls?)
Update (missed one, sort of.. ;-p)
OP found a specific in the framework which I'll include here for future reference:
In the end, the issue was with $('#TestScreen_mobileimage_1').src =
policy_shot ; I'm using Appery.io and they don't support .src.
It's $('#TestScreen_mobileimage_1').attr("src", policy_shot ) ;
A final note: localStorage is very limited in regards to storing images. Typical storage space is 2.5 - 5 mb. Each char stored takes 2 bytes and storing a data-uri encoded as base-64 is 33% larger than the original - so space will be scarce. Look into Indexed DB, Web SQL or File API for good alternatives.

Here the complete solution using File Api
<html>
<body>
<input type="file" id="image-input" />
<img id="image-container" />
<script type="text/javascript">
(function(){
/** #type {Node} */
var imgInput = document.getElementById( "image-input" ),
/** #type {Node} */
imgContainer = document.getElementById( "image-container" ),
/** Restore image src from local storage */
updateUi = function() {
imgContainer.src = window.localStorage.getItem( "image-base64" );
},
/** Register event listeners */
bindUi = function(){
imgInput.addEventListener( "change", function(){
if ( this.files.length ) {
var reader = new FileReader();
reader.onload = function( e ){
window.localStorage.setItem( "image-base64", e.target.result );
updateUi();
};
reader.readAsDataURL( this.files[ 0 ] );
}
}, false );
};
updateUi();
bindUi();
}());
</script>
</body>
</html>

Related

Can I set the filename of a PDF object displayed in Chrome?

In my Vue app I receive a PDF as a blob, and want to display it using the browser's PDF viewer.
I convert it to a file, and generate an object url:
const blobFile = new File([blob], `my-file-name.pdf`, { type: 'application/pdf' })
this.invoiceUrl = window.URL.createObjectURL(blobFile)
Then I display it by setting that URL as the data attribute of an object element.
<object
:data="invoiceUrl"
type="application/pdf"
width="100%"
style="height: 100vh;">
</object>
The browser then displays the PDF using the PDF viewer. However, in Chrome, the file name that I provide (here, my-file-name.pdf) is not used: I see a hash in the title bar of the PDF viewer, and when I download the file using either 'right click -> Save as...' or the viewer's controls, it saves the file with the blob's hash (cda675a6-10af-42f3-aa68-8795aa8c377d or similar).
The viewer and file name work as I'd hoped in Firefox; it's only Chrome in which the file name is not used.
Is there any way, using native Javascript (including ES6, but no 3rd party dependencies other than Vue), to set the filename for a blob / object element in Chrome?
[edit] If it helps, the response has the following relevant headers:
Content-Type: application/pdf; charset=utf-8
Transfer-Encoding: chunked
Content-Disposition: attachment; filename*=utf-8''Invoice%2016246.pdf;
Content-Description: File Transfer
Content-Encoding: gzip
Chrome's extension seems to rely on the resource name set in the URI, i.e the file.ext in protocol://domain/path/file.ext.
So if your original URI contains that filename, the easiest might be to simply make your <object>'s data to the URI you fetched the pdf from directly, instead of going the Blob's way.
Now, there are cases it can't be done, and for these, there is a convoluted way, which might not work in future versions of Chrome, and probably not in other browsers, requiring to set up a Service Worker.
As we first said, Chrome parses the URI in search of a filename, so what we have to do, is to have an URI, with this filename, pointing to our blob:// URI.
To do so, we can use the Cache API, store our File as Request in there using our URL, and then retrieve that File from the Cache in the ServiceWorker.
Or in code,
From the main page
// register our ServiceWorker
navigator.serviceWorker.register('/sw.js')
.then(...
...
async function displayRenamedPDF(file, filename) {
// we use an hard-coded fake path
// to not interfere with legit requests
const reg_path = "/name-forcer/";
const url = reg_path + filename;
// store our File in the Cache
const store = await caches.open( "name-forcer" );
await store.put( url, new Response( file ) );
const frame = document.createElement( "iframe" );
frame.width = 400
frame.height = 500;
document.body.append( frame );
// makes the request to the File we just cached
frame.src = url;
// not needed anymore
frame.onload = (evt) => store.delete( url );
}
In the ServiceWorker sw.js
self.addEventListener('fetch', (event) => {
event.respondWith( (async () => {
const store = await caches.open("name-forcer");
const req = event.request;
const cached = await store.match( req );
return cached || fetch( req );
})() );
});
Live example (source)
Edit: This actually doesn't work in Chrome...
While it does set correctly the filename in the dialog, they seem to be unable to retrieve the file when saving it to the disk...
They don't seem to perform a Network request (and thus our SW isn't catching anything), and I don't really know where to look now.
Still this may be a good ground for future work on this.
And an other solution, I didn't took the time to check by myself, would be to run your own pdf viewer.
Mozilla has made its js based plugin pdf.js available, so from there we should be able to set the filename (even though once again I didn't dug there yet).
And as final note, Firefox is able to use the name property of a File Object a blobURI points to.
So even though it's not what OP asked for, in FF all it requires is
const file = new File([blob], filename);
const url = URL.createObjectURL(file);
object.data = url;
In Chrome, the filename is derived from the URL, so as long as you are using a blob URL, the short answer is "No, you cannot set the filename of a PDF object displayed in Chrome." You have no control over the UUID assigned to the blob URL and no way to override that as the name of the page using the object element. It is possible that inside the PDF a title is specified, and that will appear in the PDF viewer as the document name, but you still get the hash name when downloading.
This appears to be a security precaution, but I cannot say for sure.
Of course, if you have control over the URL, you can easily set the PDF filename by changing the URL.
I believe Kaiido's answer expresses, briefly, the best solution here:
"if your original URI contains that filename, the easiest might be to simply make your object's data to the URI you fetched the pdf from directly"
Especially for those coming from this similar question, it would have helped me to have more description of a specific implementation (working for pdfs) that allows the best user experience, especially when serving files that are generated on the fly.
The trick here is using a two-step process that perfectly mimics a normal link or button click. The client must (step 1) request the file be generated and stored server-side long enough for the client to (step 2) request the file itself. This requires you have some mechanism supporting unique identification of the file on disk or in a cache.
Without this process, the user will just see a blank tab while file-generation is in-progress and if it fails, then they'll just get the browser's ERR_TIMED_OUT page. Even if it succeeds, they'll have a hash in the title bar of the PDF viewer tab, and the save dialog will have the same hash as the suggested filename.
Here's the play-by-play to do better:
You can use an anchor tag or a button for the "download" or "view in browser" elements
Step 1 of 2 on the client: that element's click event can make a request for the file to be generated only (not transmitted).
Step 1 of 2 on the server: generate the file and hold on to it. Return only the filename to the client.
Step 2 of 2 on the client:
If viewing the file in the browser, use the filename returned from the generate request to then invoke window.open('view_file/<filename>?fileId=1'). That is the only way to indirectly control the name of the file as shown in the tab title and in any subsequent save dialog.
If downloading, just invoke window.open('download_file?fileId=1').
Step 2 of 2 on the server:
view_file(filename, fileId) handler just needs to serve the file using the fileId and ignore the filename parameter. In .NET, you can use a FileContentResult like File(bytes, contentType);
download_file(fileId) must set the filename via the Content-Disposition header as shown here. In .NET, that's return File(bytes, contentType, desiredFilename);
client-side download example:
download_link_clicked() {
// show spinner
ajaxGet(generate_file_url,
{},
(response) => {
// success!
// the server-side is responsible for setting the name
// of the file when it is being downloaded
window.open('download_file?fileId=1', "_blank");
// hide spinner
},
() => { // failure
// hide spinner
// proglem, notify pattern
},
null
);
client-side view example:
view_link_clicked() {
// show spinner
ajaxGet(generate_file_url,
{},
(response) => {
// success!
let filename = response.filename;
// simplest, reliable method I know of for controlling
// the filename of the PDF when viewed in the browser
window.open('view_file/'+filename+'?fileId=1')
// hide spinner
},
() => { // failure
// hide spinner
// proglem, notify pattern
},
null
);
I'm using the library pdf-lib, you can click here to learn more about the library.
I solved part of this problem by using api Document.setTitle("Some title text you want"),
Browser displayed my title correctly, but when click the download button, file name is still previous UUID. Perhaps there is other api in the library that allows you to modify download file name.

JavaScript: Obtain the file-size of an image from the DOM element which loaded it [duplicate]

As part of a web app, once images have been downloaded and rendered on a web page, I need to determine an image's file size (kb) and resolution within the browser context (so I could, for example, display that info on the page. This needs to be done client-side, obviously. Must be able to be solved x-browser without an ActiveX control or Java applet (IE7+, FF3+, Safari 3+, IE6 nice to have), though it doesn't have to be the same solution per browser.
Ideally this would be done using system Javascript, but if I absolutely need a JQuery or similar library (or a tiny subset of it), that could be done.
Edit:
To get the current in-browser pixel size of a DOM element (in your case IMG elements) excluding the border and margin, you can use the clientWidth and clientHeight properties.
var img = document.getElementById('imageId');
var width = img.clientWidth;
var height = img.clientHeight;
Now to get the file size, now I can only think about the fileSize property that Internet Explorer exposes for document and IMG elements...
Edit 2: Something comes to my mind...
To get the size of a file hosted on the server, you could simply make an HEAD HTTP Request using Ajax. This kind of request is used to obtain metainformation about the url implied by the request without transferring any content of it in the response.
At the end of the HTTP Request, we have access to the response HTTP Headers, including the Content-Length which represents the size of the file in bytes.
A basic example using raw XHR:
var xhr = new XMLHttpRequest();
xhr.open('HEAD', 'img/test.jpg', true);
xhr.onreadystatechange = function(){
if ( xhr.readyState == 4 ) {
if ( xhr.status == 200 ) {
alert('Size in bytes: ' + xhr.getResponseHeader('Content-Length'));
} else {
alert('ERROR');
}
}
};
xhr.send(null);
Note: Keep in mind that when you do Ajax requests, you are restricted by the Same origin policy, which allows you to make requests only within the same domain.
Check a working proof of concept here.
Edit 3:
1.) About the Content-Length, I think that a size mismatch could happen for example if the server response is gzipped, you can do some tests to see if this happens on your server.
2.) For get the original dimensions of a image, you could create an IMG element programmatically, for example:
var img = document.createElement('img');
img.onload = function () { alert(img.width + ' x ' + img.height); };
img.src='http://sstatic.net/so/img/logo.png';
Check the uploaded image size using Javascript
<script type="text/javascript">
function check(){
var imgpath=document.getElementById('imgfile');
if (!imgpath.value==""){
var img=imgpath.files[0].size;
var imgsize=img/1024;
alert(imgsize);
}
}
</script>
Html code
<form method="post" enctype="multipart/form-data" onsubmit="return check();">
<input type="file" name="imgfile" id="imgfile"><br><input type="submit">
</form>
Getting the Original Dimensions of the Image
If you need to get the original image dimensions (not in the browser context), clientWidth and clientHeight properties do not work since they return incorrect values if the image is stretched/shrunk via css.
To get original image dimensions, use naturalHeight and naturalWidth properties.
var img = document.getElementById('imageId');
var width = img.naturalWidth;
var height = img.naturalHeight;
p.s. This does not answer the original question as the accepted answer does the job. This, instead, serves like addition to it.
How about this:
var imageUrl = 'https://cdn.sstatic.net/Sites/stackoverflow/img/sprites.svg';
var blob = null;
var xhr = new XMLHttpRequest();
xhr.open('GET', imageUrl, true);
xhr.responseType = 'blob';
xhr.onload = function()
{
blob = xhr.response;
console.log(blob, blob.size);
}
xhr.send();
http://qnimate.com/javascript-create-file-object-from-url/
due to Same Origin Policy, only work under same origin
Regarding the width and height:
var img = document.getElementById('imageId');
var width = img.clientWidth;
var height = img.clientHeight;
Regarding the filesize you can use performance
var size = performance.getEntriesByName(url)[0];
console.log(size.transferSize); // or decodedBodySize might differ if compression is used on server side
Service workers have access to header informations, including the Content-Length header.
Service workers are a bit complicated to understand, so I've built a small library called sw-get-headers.
Than you need to:
subscribe to the library's response event
identify the image's url among all the network requests
here you go, you can read the Content-Length header!
Note that your website needs to be on HTTPS to use Service Workers, the browser needs to be compatible with Service Workers and the images must be on the same origin as your page.
Most folks have answered how a downloaded image's dimensions can be known so I'll just try to answer other part of the question - knowing downloaded image's file-size.
You can do this using resource timing api. Very specifically transferSize, encodedBodySize and decodedBodySize properties can be used for the purpose.
Check out my answer here for code snippet and more information if you seek : JavaScript - Get size in bytes from HTML img src
You can use generic Image object to load source dynamically then measure it:
const img = new Image();
img.src = this.getUrlSource()
img.onload = ({target}) =>{
let width = target.width;
let height = target.height;
}
You can get the dimensions using getElement(...).width and ...height.
Since JavaScript can't access anything on the local disk for security reasons, you can't examine local files. This is also true for files in the browser's cache.
You really need a server which can process AJAX requests. On that server, install a service that downloads the image and saves the data stream in a dummy output which just counts the bytes. Note that you can't always rely on the Content-length header field since the image data might be encoded. Otherwise, it would be enough to send a HTTP HEAD request.
You can find dimension of an image on the page using something like
document.getElementById('someImage').width
file size, however, you will have to use something server-side
var img = new Image();
img.src = sYourFilePath;
var iSize = img.fileSize;
The only thing you can do is to upload the image to a server and check the image size and dimension using some server side language like C#.
Edit:
Your need can't be done using javascript only.

Deploying webapp coded in impact javascript game engine locally, results in CORS on chrome

I am trying to make a webapp (developed with impact js game engine), able to run locally without the need of a localhost (using file:///C:/...) and I am required to make it work on chrome.
The main issue that it does not work on chrome is that chrome blocks my media (mainly images in png/jpg) from being loaded from media folder due to CORS issues.
After spending a few days reading up and trying a few methods I am not able to resolve this issue. Anybody with experience in this please tell me if it is possible and if it is, what methods should I go about on this.
Methods I have tried:
1) setting img.crossOrigin = "anonymous" (failed, this is still blocked by chrome)
2) opening chrome with flag --allow-file-access-from-files (worked, but not a feasible method for end user)
3) reading images and converting them to data uri format (failed, data uri conversion seems
to be not working due to inherent CORs issue)
4) attempted to use appcache to cache all images into browser cache (failed, do not seem to work as it is not being accessed from a webserver)
UPDATE: I am now trying to edit the impact.image source code to try to convert the src to data url at the point of loading into the image
load: function( loadCallback ) {
function getBase64Image(img) {
// Create an empty canvas element
var img2 = document.createElement("img");
var canvas2 = document.createElement("canvas");
// Copy the image contents to the canvas
var ctx2 = canvas2.getContext("2d");
img2.onload = function(){
canvas2.width = img2.width;
canvas2.height = img2.height;
};
img2.onerror = function() {console.log("Image failed!");};
img2.src = img + '?' + Date.now();
ctx2.drawImage(img2, 0, 0, img2.width, img2.height);
return canvas2.toDataURL("image/png");
}
if( this.loaded ) {
if( loadCallback ) {
loadCallback( this.path, true );
}
return;
}
else if( !this.loaded && ig.ready ) {
this.loadCallback = loadCallback || null;
this.data = new Image();
this.data.onload = this.onload.bind(this);
this.data.onerror = this.onerror.bind(this);
//this.data.src = ig.prefix + this.path + ig.nocache;
//old src sets to local file, new src sets to data url generated
this.data.src = getBase64Image(this.path);
}
else {
ig.addResource( this );
}
ig.Image.cache[this.path] = this;
},
for some reason the image is not being loaded into the function, will it work even if i get the image load to load into the getBase64Image function?
Short of saving everything as pre-generated, Base-64 data-uris, which you bake into a JS file, or a script tag on your "index.HTML" page, you aren't going to have much luck here -- especially if your intent is to distribute this to an audience disconnected from a webserver (to at least provide a domain for the appcache).
Mind you, in order to generate the data-uris, you, yourself are probably going to require localhost (or a build-tool).

WebSocket JavaScript: Sending complex objects

I am using WebSockets as the connection between a Node.js server and my client JS code.
I want to send a number of different media types (Text, Audio, Video, Images) through the socket.
This is not difficult of course. message.data instanceof Blob separates text from media files. The problem is, that I want to include several additional attributes to those media files.
F.e.:
Dimension of an image
Name of the image
. . .
Now I could send one message containing these informations in text form and follow it up with another message containing the blob.
I would very much prefer though, to be able to build an object:
imageObject = {
xDimension : '50px',
yDimension : '50px',
name : 'PinkFlowers.jpg'
imageData : fs.readFileSync(".resources/images/PinkFlowers.jpg")
}
And send this object as it is via socket.send(imageObject).
So far so good, this actually works, but how do I collect the object and make its fields accessible in the client again?
I have been tampering with it for a while now and I would be grateful for any ideas.
Best regards,
Sticks
Well I did get it to work using base64.
On the server side I am running this piece of code:
var imageObject = newMessageObject('img', 'flower.png');
imageObject.image = new Buffer(fs.readFileSync('./resources/images/flower.png'), 'binary').toString('base64');
imageObject.datatype = 'png';
connection.send(JSON.stringify(imageObject));
The new Buffer() is necessary to ensure a valid utf encoding. If used without, Chrome(dont know about Firefox and others) throws an error, that invalid utf8 encoding was detected and shuts down the execution after JSON.parse(message).
Note: newMessageObject is just an object construction method with two fields, type and name which I use.
On the client side its really straight forward:
websocketConnection.onmessage = function(evt) {
var message = JSON.parse(evt.data);
... // Some app specific stuff
var image = new Image();
image.onload = function() {
canvas.getContext("2d").drawImage(image, 0, 0);
}
image.src = "data:image/" + message.datatype + ";base64," + message.image;
}
This draws the image on the canvas.
I am not convinced, that this is practicable for audio or video files, but for images it does the job.
I will probably fall back to simply sending an obfuscated URL instead of audio/video data and read the files directly from the server. I dont like the security implications though.

Determining image file size + dimensions via Javascript?

As part of a web app, once images have been downloaded and rendered on a web page, I need to determine an image's file size (kb) and resolution within the browser context (so I could, for example, display that info on the page. This needs to be done client-side, obviously. Must be able to be solved x-browser without an ActiveX control or Java applet (IE7+, FF3+, Safari 3+, IE6 nice to have), though it doesn't have to be the same solution per browser.
Ideally this would be done using system Javascript, but if I absolutely need a JQuery or similar library (or a tiny subset of it), that could be done.
Edit:
To get the current in-browser pixel size of a DOM element (in your case IMG elements) excluding the border and margin, you can use the clientWidth and clientHeight properties.
var img = document.getElementById('imageId');
var width = img.clientWidth;
var height = img.clientHeight;
Now to get the file size, now I can only think about the fileSize property that Internet Explorer exposes for document and IMG elements...
Edit 2: Something comes to my mind...
To get the size of a file hosted on the server, you could simply make an HEAD HTTP Request using Ajax. This kind of request is used to obtain metainformation about the url implied by the request without transferring any content of it in the response.
At the end of the HTTP Request, we have access to the response HTTP Headers, including the Content-Length which represents the size of the file in bytes.
A basic example using raw XHR:
var xhr = new XMLHttpRequest();
xhr.open('HEAD', 'img/test.jpg', true);
xhr.onreadystatechange = function(){
if ( xhr.readyState == 4 ) {
if ( xhr.status == 200 ) {
alert('Size in bytes: ' + xhr.getResponseHeader('Content-Length'));
} else {
alert('ERROR');
}
}
};
xhr.send(null);
Note: Keep in mind that when you do Ajax requests, you are restricted by the Same origin policy, which allows you to make requests only within the same domain.
Check a working proof of concept here.
Edit 3:
1.) About the Content-Length, I think that a size mismatch could happen for example if the server response is gzipped, you can do some tests to see if this happens on your server.
2.) For get the original dimensions of a image, you could create an IMG element programmatically, for example:
var img = document.createElement('img');
img.onload = function () { alert(img.width + ' x ' + img.height); };
img.src='http://sstatic.net/so/img/logo.png';
Check the uploaded image size using Javascript
<script type="text/javascript">
function check(){
var imgpath=document.getElementById('imgfile');
if (!imgpath.value==""){
var img=imgpath.files[0].size;
var imgsize=img/1024;
alert(imgsize);
}
}
</script>
Html code
<form method="post" enctype="multipart/form-data" onsubmit="return check();">
<input type="file" name="imgfile" id="imgfile"><br><input type="submit">
</form>
Getting the Original Dimensions of the Image
If you need to get the original image dimensions (not in the browser context), clientWidth and clientHeight properties do not work since they return incorrect values if the image is stretched/shrunk via css.
To get original image dimensions, use naturalHeight and naturalWidth properties.
var img = document.getElementById('imageId');
var width = img.naturalWidth;
var height = img.naturalHeight;
p.s. This does not answer the original question as the accepted answer does the job. This, instead, serves like addition to it.
How about this:
var imageUrl = 'https://cdn.sstatic.net/Sites/stackoverflow/img/sprites.svg';
var blob = null;
var xhr = new XMLHttpRequest();
xhr.open('GET', imageUrl, true);
xhr.responseType = 'blob';
xhr.onload = function()
{
blob = xhr.response;
console.log(blob, blob.size);
}
xhr.send();
http://qnimate.com/javascript-create-file-object-from-url/
due to Same Origin Policy, only work under same origin
Regarding the width and height:
var img = document.getElementById('imageId');
var width = img.clientWidth;
var height = img.clientHeight;
Regarding the filesize you can use performance
var size = performance.getEntriesByName(url)[0];
console.log(size.transferSize); // or decodedBodySize might differ if compression is used on server side
Service workers have access to header informations, including the Content-Length header.
Service workers are a bit complicated to understand, so I've built a small library called sw-get-headers.
Than you need to:
subscribe to the library's response event
identify the image's url among all the network requests
here you go, you can read the Content-Length header!
Note that your website needs to be on HTTPS to use Service Workers, the browser needs to be compatible with Service Workers and the images must be on the same origin as your page.
Most folks have answered how a downloaded image's dimensions can be known so I'll just try to answer other part of the question - knowing downloaded image's file-size.
You can do this using resource timing api. Very specifically transferSize, encodedBodySize and decodedBodySize properties can be used for the purpose.
Check out my answer here for code snippet and more information if you seek : JavaScript - Get size in bytes from HTML img src
You can use generic Image object to load source dynamically then measure it:
const img = new Image();
img.src = this.getUrlSource()
img.onload = ({target}) =>{
let width = target.width;
let height = target.height;
}
You can get the dimensions using getElement(...).width and ...height.
Since JavaScript can't access anything on the local disk for security reasons, you can't examine local files. This is also true for files in the browser's cache.
You really need a server which can process AJAX requests. On that server, install a service that downloads the image and saves the data stream in a dummy output which just counts the bytes. Note that you can't always rely on the Content-length header field since the image data might be encoded. Otherwise, it would be enough to send a HTTP HEAD request.
You can find dimension of an image on the page using something like
document.getElementById('someImage').width
file size, however, you will have to use something server-side
var img = new Image();
img.src = sYourFilePath;
var iSize = img.fileSize;
The only thing you can do is to upload the image to a server and check the image size and dimension using some server side language like C#.
Edit:
Your need can't be done using javascript only.

Categories