简体   繁体   中英

How to send just uploaded image to php without store it?

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 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 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 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 the preview of the selected image only works with JavaScript enabled, but the form will submit the selected file to your chosen URL (here http://httpbin.com/post , at a convenient test server, which just echoes back your uploaded content in the form of a JSON file) regardless. You can thus intercept the POST'ed data with your PHP script and act accordingly.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM