Hi I'll introducing my problem directly with the use case: I'm working on a sort of configurator and I have a web page (let's call it page1) where the user can upload an image. The image is showed normally in an img tag. When the user has uploaded the image he can go forward on the next page (let's call it page2). Now, on this page2 I want to show the image uploaded by user without storing the image. This is what I've tried 'till now:
Before to do this I've inserted in the json the src attribute of the image directly. But the browser gave me te error that the GET request is too long or something like that. So, I've found as solution to convert the image with base64:
function getBase64Image(img) {
var canvas = document.createElement("canvas");
canvas.width = img.width;
canvas.height = img.height;
var ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0);
var dataURL = canvas.toDataURL("image/png");
return dataURL.replace(/^data:image\/(png|jpg);base64,/, "");
}
function sendSelectedProducts()
{
var logo = document.getElementsByName('logo-container')[0];
var base64 = getBase64Image(logo);
console.log(base64);
var json_string = '{"img": "' + base64 + '" }';
console.log(json_string);
window.location.replace('riepilogo.php?prodotti=' + json_string);
}
So, what I'm doing with this code is to send a Json with a base64-converted image. On the PHP-side this is the code that tries to convert back the image:
function base64ToImage($base64_string, $output_file) {
$file = fopen($output_file, "wb");
$data = explode(',', $base64_string);
fwrite($file, base64_decode($base64_decode));
fclose($file);
return $output_file;
}
echo '<p>'.$img.'</p>';
echo '<a class="cart-image" href="#"><img src="'.base64ToImage($img, 'logo_file.jpg').'" alt="logo"></a>'?>
This code doesn't work and I'm looking for solution that does not store the image on the server. How can I do?
You don't need to decode the image from base64, just do this:
echo '<a class="cart-image" href="#"><img src="data:'.$img.'" alt="logo"></a>'?>
where $img is the image in base64 format. For more info see: How to display Base64 images in HTML?
You can save the selected file (for example in a window var or local storage) and render the image in the next page using canvas.
See following example, please:
function saveImage(img) {
window.file = img.files[0];
}
function loadImage() {
let ctx = document.getElementById('canvas').getContext('2d');
let url = URL.createObjectURL(window.file);
let img = new Image();
img.onload = function() {
ctx.drawImage(img, 20, 20);
}
img.src = url;
}
<input type="file" id="imgFile" onchange="saveImage(this);" />
<button onclick="loadImage()">Load image</button>
<canvas width="400" height="300" id="canvas"/>
You should put saveImage in the first page and loadImage in the second page.
I hope it was clear. Bye.
You need to know how HTTP works to understand why what you're doing is not going to work.
HTTP is the way browsers and Web servers (which can run PHP code) communicate.
One important thing to keep in mind here is that between any two Web pages there is no state to share for the Web server -- this is why HTTP is often called a stateless protocol. That's a good thing -- it saves on a lot of unneeded complexity for the Web server (and PHP).
I would not recommend attempting to circumvent the stateless nature of HTTP with things like window.localStorage (or sessionStorage for that matter) -- what if the user has loaded several instances of the same Web page on your website? How are you going to know which objects in your storage correspond to which upload workflow(s)?
I've seen many people try to do that, and it always breaks eventually.
There are several good ways to solve the "stateless" problem in your case -- how can a file uploaded with one Web page, be accessible to another, and yet making the file also available to the Web server?
In this answer I want to cover a so-called single Web page application solution, where you simply do away with two Web pages and instead have one Web page that does everything! This way you keep the state on the client but also in a clean manner that aligns well with how HTTP actually works:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<form enctype="multipart/form-data" method="post" action="http://httpbin.org/post">
<label for="file-input">Select an image file</label>
<input accept="image/*" id="file-input" name="image" type="file">
<label for="file-selection-preview-image">Selected image</label>
<img id="file-selection-preview-image"><!-- this element will display selected image. -->
<input type="submit">
<script>
const form = document.currentScript.parentElement, file_input = form.elements.image;
file_input.addEventListener("change", function(ev) { /// Whenever the selection changes
const files = ev.target.files;
console.assert(files.length == 1); /// Assert that there is only one file selected
console.assert(files[0].type.startsWith("image/")); /// Assert that the selected file is an image
const image = form.querySelector("img");
if(image.src) URL.revokeObjectURL(image.src); /// The kind of URLs we are dealing with refer to in-memory objects, so we have to dispose of them when we no longer need them -- the user agent does not do this for us automatically.
image.src = URL.createObjectURL(files[0]); /// Display selected file with the `img` element
});
/// User agent is free to retain file selection even after the Web page has been re-loaded, so if there is [a selection], we fire a "change" event manually so that the handler defined above may reflect this as it ordinarily would.
if(file_input.files.length) file_input.dispatchEvent(new Event("change", { bubbles: true }));
</script>
</form>
</body>
</html>
The above HTML document is set up with a simple form (which will let you upload files to your Web server even without JavaScript enabled). It contains a file input control that lets you actually select files (a single image file, since the input element does not contain the multiple attribute and specifies image/* for the accept attribute).
However, it also contains an img element which a script uses to load and display the selected image file with, immediately upon selection. I understand from your question that this may satisfy your requirement of accessing the selected file. The file is a Blob so you can do what you want with it, including drawing it in a canvas and modifying it otherwise. Here I just display it as an image.
The interesting property of the Web page is that while preview of the selected image only works through JavaScript, the form will still submit the selected file even without JavaScript. The user agent will post form data (image) to a convenient test server (at http://httpbin.com/post), which just happens to echo back your uploaded content in the form of a JSON file. With own service, you can handle the data yourself.
This solves the problem of multiple Web pages needing to share access to selected file, which would, if implemented properly, at least require uploading the file first and then accessing it from a URL the upload establishes on your Web server. Not necessarily more complicated than the solution in this answer, in fact arguably less complicated because it's how it has been done before JavaScript started allowing the kind of things I make use of in the document pasted above. But I would argue that this answer that covers a so-called single-page Web application, should fit you fine in this day and age.
That said, I consider a pure PHP solution to be interesting as well, and can pen up another answer should anyone wish to see one.
Related
EDIT
The source of this problem is the behavior of the Edge browser, as identified by Sami. Firefox does the same thing, but Chrome works fine.
Original Question
I have a drop container for users to drag and drop an image to set an <input type="file"> with the image.
If the image is being dragged and dropped from a different page, the image is recognized as a file. However, if the image is dragged and dropped from the same page with the drop container, it is recognized as a URL.
Why isn't the image being recognized as a file when it is dragged and dropped from the same page as the drop container?
Here is the fiddle with the drop container and image file. When you drag the image file on this page into the drop container, it is recognized as a URL although I want it to be recognized as a file.
https://jsfiddle.net/nadf9c82/1/
Next, try dragging the image on this fiddle https://jsfiddle.net/7sqb5r0f/1/ into the drop container on the other fiddle and you will see it is recognized as a file, which is what I want.
Why do images on the same page as the drop container evaluate as URLs and not files? Is there a fix to make them recognized as files and not URLs?
Here is the code for reference
<div class="dropContainer" id="dropContainer">Drop Here</div>
<div id="imagetwo">
<img src="http://a.mktgcdn.com/p/khxNbcdQcr1HQKNgk9cPNUyWUprmZ5Dryx9P5MAV0SE/2669x3840.jpg" />
</div>
<script>
dropContainer.ondrop = function(evt) {
//evt.preventDefault();
if(evt.dataTransfer.files[0]){
console.log("is a file");
const dT = new DataTransfer();
dT.items.add(evt.dataTransfer.files[0]);
fileInput.files = dT.files;
}else{
// Try dataTransfer url second
var dataTransferUrl = evt.dataTransfer.getData('url');
if(dataTransferUrl){
console.log('is a url, not a file');
console.log(dataTransferUrl);
}
}
};
</script>
I think you can do it, but it won't work in Fiddle due to The page at 'https://jsfiddle.net/' was loaded over HTTPS, but requested an insecure resource ... the content must be served over HTTPS due to your HTTP request
Here's what I think, whenever you drop the image, it'll receive an URL instead of the file like you want. Then just make it into a file.
It's called convert your URL image to File object, if my way is not working, it's the keyword for you to have a look more, I hope it'll give you some ways to work around since I'm not good at this, too.
Replace this code of mine into your Try dataTransfer URL second part, but be warned that it'll fire an error on Fiddle due to HTTP request. So I've to replace the HTTP with HTTPS, but it'll get you the CORS Block, so if you have the extension to unblock CORS, it'll work, for development or testing purposes, of course.
let url = evt.dataTransfer.getData('url');
const urlArray = Array.from(url)
urlArray.splice(4, 0, 's')
const urlFinal = urlArray.join('')
fetch(urlFinal)
.then(async (res) => {
const contentType = await res.headers.get('Content-Type')
const blob = await response.blob()
const file = new File([blob], "image.jpeg", { contentType })
})
}
When I drop an image to Drop Here box, it'll create an Object File, so it'll count as a file instead of an URL, I think that's what you want, hope I can help you somehow.
Take an URL as an Object File after Dragging Image and Drop it into Drop Here Box
Can I take a screenshot from the clipboard, send it to ajax and put it in an <img> tag?
For example,
I have this form:
<form>
<div id="img"><img src="need put screen here!"></div>
<textarea></textarea>
<button type="submit">Answer!</button>
</form>
I need it! People are asking for screenshots from the clipboard.
If the screen stays in the clipboard in code base64, I make it to a picture in PHP.
I only don't know, how I can take a screenshot from the clipboard and send it to ajax.
Yes, you can:
Capture data in the clipboard as pasted within your Web page
Upload said data somewhere via HTTP
Display said data as an image within your Web page
To obtain data in the clipboard you attach an event listener for the "paste" event type. The event is fired on the active document element and bubbles all the way upwards the element hierarchy towards the document window.
The ClipboardEvent object that your event listener is passed, will let you obtain the actual data in the clipboard, text and/or image:
addEventListener("paste", ev => {
for(const item of ev.clipboardData.items) { /// Clipboard may contain multiple elements of different type -- text, image, etc
if(item.type.startsWith("image/")) { /// We are only interested in clipboard data that is an image
/// Do something with the data, image available as `item.getAsFile()`
}
}
});
The image data would be available with item.getAsFile(), a File (subclass of Blob). You can upload the blob trivially:
var xhr = new XMLHttpRequest();
xhr.open("PUT", "http://example.com");
xhr.send(item.getAsFile()); /// Send the image with HTTP somewhere
You can also display the pasted image, assuming you have <img id="foobar"> somewhere in your document:
document.getElementById("foobar").src = URL.createObjectURL(item.getAsFile());
You can use html2canvas, to take screenshots and upload them, all using JavaScript.
Use the following to take screenshot of current screen:
html2canvas(document.body).then(function(canvas) {
});
then use canvas.toDataURL(); to convert image to base64 and upload.
I have a page on a website that is just an image tag. When the page is loaded, it makes an API call and changes the source of the image depending what picture is available that day. For example, after an API call has been made (with an example picture):
<head>
<body>
<img src="http://www.tizag.com/pics/htmlT/sunset.gif"/>
</body>
</head>
My goal is to be able to use the URL of the page with just the image as the source of an image on any other page. Other sites would then be able to use the URL of the page with the image.
In other words, how would I take the source of the image on the page above and use it is the source of an image on a different page?
I'm not sure that I completely understand Your issue, but can't You just use the same source URL on other pages?
Maybe You want to have reference to that image so when You want to change this image on all pages You wouldn't have to do this on all pages but just one. Then it would be simpler to just replace file.
I think you should use javascript script that would be verifying which image should be displayed.
Can't you just use the same API to get the source on the other site?
If you can't:
First, get the XML from the image-only-site and parse it as DOM elements.
Next, get the img element's source.
$.ajax({
url: 'your-url', success: function(data) {
var xmlString = data, parser = new DOMParser(),
doc = parser.parseFromString(xmlString, "text/xml");
var src = doc.firstChild.src;
}
});
I've successfully allowed for a user to upload an image to local storage but I want to be able to then take that image and fill an image element on the page with that.
<h3>Please upload the image you wish to use.</h3>
<input id="photoin" type="file" accept="image/*;capture=camera"></input>
Submit
<script>
var i = 0;
function save(){
var input = document.getElementById("photoin").value;
var name = "photo_" + i;
localStorage.setItem(name, input);
$("#QR").src = window.localStorage[name];
i++;
}
</script>
I'm looking for something that will successfully give me the URL of the image in storage, seeing as "window.localStorage[name]" only returns the value paired with that key.
Thanks!
Well you can store the actual image data in localStorage (though be wary - there's a limit)
Have a look at the HTML5 rocks tutorial & scroll down to the bit headed READING FILES
Here the file is being read then the output put in the img:src tag. You could additionally put it in localStorage
Example: http://jsfiddle.net/8V9w6/ - select an image file, see the thumbnail? Then reload the page. The thumbnail should remain there. (Works latest Chrome/Firefox)
In one webpage, I have a big image to load and other contents. Sometimes the image takes longer time to load and I would like to track that. Is there any means by which I can get notified using Javascript when browser completely renders the image?
EDIT
I use the following code to load the image.
<table border="0" style="background-image: url(http://abc.com/abc.jpg);" id="imageDisp">
</table>
SOME More UPDATE
Is there any simple way to know how long the image took to render? Using the javascript I am getting a notification that the image is loaded now, is there a way to know when the image load started? So that the elapsed time can be calculated?
You can hook on the load event of the <img> element. E.g.
<img src="http://upload.wikimedia.org/wikipedia/commons/3/31/Atlantic_hurricane_tracks.jpg"
onload="alert('finished!');">
Jsfiddle demo.
Update:
Then create new Image() instead (the average browser is smart enough not to request the same image twice and multiple references will point to the same image request):
<script>
var img = new Image();
img.src = 'http://upload.wikimedia.org/wikipedia/commons/3/31/Atlantic_hurricane_tracks.jpg';
img.onload = function() {
alert('finished!');
}
</script>
Another jsfiddle demo (don't forget to clear browser cache, the same image might be already cached :) ).