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.