Jump to content

Redundant Image path segment


TechnoDiver

Recommended Posts

I'm trying to display some user created content on a page. Everything does what it should except the image (it's always the image). To be clear, I'm not storing the image in the DB only the link to the image, but images are being uploaded into the site file system.

The path being stored in the DB (phpmyadmin) is the full image path - /opt/lampp/htdocs/site/news/img/posts/* -

The image doesn't display on the page and I get a 404 not found in the console.

When I echo the path to the page that it's looking for the image in, it's as above. But the 404 not found in the console says it's looking for it at http://localhost/opt/lampp/htdocs.... So it's obviously got a redundant section (http://localhost).

When I try to remove the /opt/lampp/htdocs from the upload path I get a bunch of warnings. But the real issue is that the browser is adding the repeated section.

So how do I remedy this so the browser looks in the correct location? TIA

Link to comment
Share on other sites

47 minutes ago, Barand said:

Try specifying the image path from your site's root, not the file system root. ie "/news/img/posts/"

Yea, I originally had it fully hard coded in as in my OP -> "/opt/lampp/htdocs/site/news/img/posts/"

and the browser looks for the images in "http://localhost/opt/lampp/htdocs/site..."

So after my OP I tried

$_SERVER['DOCUMENT_ROOT'] . /site/news...

the browser still looks for it in "http://localhost/opt/lampp/htdocs/site..."

The really confusing part is if I only hard code the path -> "/site/news/img/posts/" dropping the "/opt/lampp/htdocs/"  part

then the browser looks for it in "http://localhost/site/news/site/news/img/post/"

So either way I get a repetitive path segment and I have no idea why or how to fix it

Link to comment
Share on other sites

Stop storing the dumb "/opt/lampp/htdocs" portion in the database and store only the relative path. In fact, if you're talking about a table and column where you know the image is always going to be in /site/news/img/posts then all you have to store is the filename.

Or in other words, store only the part of the filename that your code won't already know about.

Link to comment
Share on other sites

6 minutes ago, requinix said:

Stop storing the dumb "/opt/lampp/htdocs" portion in the database and store only the relative path. In fact, if you're talking about a table and column where you know the image is always going to be in /site/news/img/posts then all you have to store is the filename.

Or in other words, store only the part of the filename that your code won't already know about.

I mentioned in my first response that I tried dropping the /opt/lampp/htdocs/ and when I only use /site/news/img/posts/ the browser looks in "https://localhost/site/news/site/news/img/posts/. So on both methods there's a section getting repeated.

 

Link to comment
Share on other sites

14 minutes ago, requinix said:

Uh huh. Have you reached the point where all you're storing is the part of the filename that your code won't already know about?

There are a few test entries that have stored the path "site/news/img/posts/" yes. That was actually the original way I tried in the beginning. The problem then is not only does the browser console say it's looking for it in "http://localhost/site/news/site/news.." repeating the /site/news/ segment but I also get these warnings:

Quote

Warning: move_uploaded_file(/opt/lampp/htdocs/newsnet/img/posts/610f1962cc3621.48842272.jpeg): Failed to open stream: No such file or directory in /opt/lampp/htdocs/qcic/usernet/content/add_post.php on line 27

 

 

Warning: move_uploaded_file(): Unable to move "/tmp/phpvOZgc1" to "/opt/lampp/htdocs/newsnet/img/posts/610f1962cc3621.48842272.jpeg" in /opt/lampp/htdocs/qcic/usernet/content/add_post.php on line 27
/opt/lampp/htdocs/newsnet/img/posts/610f1962cc3621.48842272.jpeg

 

and the data still goes into the database. The only way I was able to get this resolved was by using the full path -> /opt/lampp/htdocs/site/newsnet/img/posts/

So by not putting in the full path I have 2 issues and with the full path I have the issue of redundant path segments. And I've no idea why.

When I echo the contents of the variable that I push into <img src= ...> (where it should display the image and isn't) it echos just the full path with no repeated segments but the browser console returns the paths with repeated segments. So I'm pretty lost as to how to fix it

 

Edited by TechnoDiver
Link to comment
Share on other sites

Stop worrying about what you're seeing in the browser for a while. If you fix the underlying problems then stuff in the browser will magically start to work.

Let's go one step at a time.

An image gets uploaded. Because it's a news thing, you want to store it in /opt/lampp/htdocs/news/img/posts/. Is there any reason qcic/usernet/content/add_post.php will want to store the file anywhere else? Does it handle other types of uploads? If so, how does it handle the different types when it comes to where uploaded images go and what database tables get updated?

Link to comment
Share on other sites

7 minutes ago, requinix said:

Because it's a news thing, you want to store it in /opt/lampp/htdocs/news/img/posts/.

Ok, the actual full path is '/opt/lampp/htdocs/qcic/newsnet/img/posts/'

The add_post.php file is in '/opt/lamp/htdocs/qcic/usernet/content/add_post.php', so the common path for them is '/opt/lampp/htdocs/qcic/'

This is my code at the top of add_post.php and I see no reason why it would want to dl elsewhere ->

<?php
require("assets/initializations.php");

mysqli_report(MYSQLI_REPORT_ERROR|MYSQLI_REPORT_STRICT);

if(isset($_POST['add_post']) && !empty($_FILES['post_image'])) {
    $filename = $_FILES['post_image']['name'];
    $file_tmp_name = $_FILES['post_image']['tmp_name'];
    $filesize = $_FILES['post_image']['size'];

    echo "this is the file temp name " . $file_tmp_name . "<br>";

    $file_ext = explode('.', $filename);
    $file_act_ext = strtolower(end($file_ext));
    $allowed = array('jpeg', 'jpg', 'png', 'gif');


    if(!in_array($file_act_ext, $allowed)) {
        echo "<script>alert('File Type Not Allowed');</script>";
        //not sure how well this size check is working, have to experiment more
        //also need to research how to do an initial image check
    } elseif($filesize > 10000000) {
        echo "<script>alert('Image Is Too Large');</script>";

    } else {
        $file_new_name = uniqid('', true) . "." . $file_act_ext;
        $dir = "/newsnet/img/posts/";
        $target_file = $dir . basename($file_new_name);

        echo "this is the target file " . $target_file;
        
        move_uploaded_file($file_tmp_name, $target_file);

        $post_obj->addNews(
            $_POST['title'], $_POST['content'], $_POST['category'], 
            $_POST['status'], $_POST['post_type'], $_POST['tags'], $target_file
        );

        echo "<script>alert('Your Post Has Been Added');</script>";
        echo $target_file;
        // mysqli_report(MYSQLI_REPORT_ERROR|MYSQLI_REPORT_STRICT);
    }
}

You'll see that $dir is where I've been experimenting with the path and there's some unnecessary echo statements I was confirming things with. It doesn't yet handle any other uploads. It's meant to rename the image, move it into the sites directory structure and then send the link to it into the DB with the rest of the user input. It does that, so far so good..

This is the method that handles that ->

public function addNews($title, $content, $category, $status, $type, $tags, $image) {
            if(!empty($title) && !empty($content)) {
                $title = strtoupper($title);
                $title = mysqli_real_escape_string($this->conn, $title);

                $content = nl2br($content);
                $content = mysqli_real_escape_string($this->conn, $content);

                $added_by = $this->user_obj->getUsername();

                $query = mysqli_query($this->conn, "SELECT top_cat_id FROM top_categories WHERE top_cat_title='$category'");
                $row = mysqli_fetch_array($query);
                $cat_id = $row['top_cat_id'];
                $date_added = date('Y-m-d H:i:s');

                //these may have to be moved/assigned somewhere else eventually
                $num_likes = 0;
                $num_comments = 0;
                $num_views = 0;

                $statement = $this->conn->prepare("INSERT INTO news (
                    title, content, add_by, post_category, post_cat_id, post_image, tags, status, type, num_likes, num_comments, num_views, date_added
                    ) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?);");

                $statement->bind_param('ssssissssiiis', $title, $content, $added_by, $category, $cat_id, $image, $tags, $status, $type, $num_likes, $num_comments, $num_views, $date_added);
                
                if($statement) {
                    $statement->execute();
                } 
            }
        }

And again, I see nowhere that there's a clash of download locations or the like. I hate flooding one post with a bunch of code, but there is another method involved with displaying these images ->

public function getBreakingNews() {
            $query = mysqli_query($this->conn, "SELECT * FROM news WHERE type='breaking' ORDER BY RAND()");
            $str = "";
            while($row = mysqli_fetch_array($query)) {
                $id = $row['id'];
                $title = $row['title'];
                $content = $row['content'];
                
                // if(strlen($content) > 200) {
                //     $content = substr($content, 0, 200) . "...";
                // }

                $added_by = $row['add_by'];
                $cat_title = $row['post_category'];
                $cat_id = $row['post_cat_id'];
                $image = $row['post_image'];
                $likes = $row['num_likes'];
                $comments = $row['num_comments'];
                $date_added = $row['date_added'];

                $current_datetime = date("Y-m-d H:i:s");
                
                $start_count = new DateTime($date_added);
                $end_count = new DateTime($current_datetime);
                $interval = $start_count->diff($end_count);

                // $image = substr($image, 13);
                echo $image;

                if($interval->h <= 8) {
                    $str .= "
                    <div class='single-blog-post small-featured-post d-flex'>
                        <div class='post-thumb'>
                        
                            <a href='#'><img src='$image' alt=''></a>
                        </div>
                        <div class='post-data'>
                            <a href='#' class='post-category text-size-6'>$cat_title</a>
                            <div class='post-meta'>
                                <a href='#' class='post-title'>
                                    <h6>$title</h6>
                                </a>
                                <p class='post-date'><span>Hour:minute</span> | <span>month:day</span></p>
                            </div>
                        </div>
                    </div>";
                }
            }

            // mysqli_report(MYSQLI_REPORT_ERROR|MYSQLI_REPORT_STRICT);
            echo $str;
        }
    }

and again, this one works fine for everything except the image. So I realize I've got something not happening correctly, but I've been working on this issue on and off since last weekend and I can't get those images displayed. It's why I kept mentioning the browser console output, but I understand why the underlying cause should be the focus..

Link to comment
Share on other sites

23 minutes ago, TechnoDiver said:

You'll see that $dir is where I've been experimenting with the path and there's some unnecessary echo statements I was confirming things with.

You don't have to experiment with anything. Just stop and spend a couple minutes thinking about it logically.

1. All your images are in the same qcic/newsnet/img/posts/ directory.
2. Storing "qcic/newsnet/img/posts/" inside every single row in that one database table is incredibly repetitive. Even moreso the /opt/lampp/htdocs root. You know that all the images are in the one place.
3. Obviously you do have to store something. Why? Because there comes a time when you need to know a URL for a file and you won't know a certain part of it. So what do you need to store? The part of the filename you don't know.
4. If all your images are in the same posts/ directory (as in you're not storing them in additional subdirectories, like putting 610f1962cc3621.48842272.jpeg into /61/0f/610f1962cc3621.48842272.jpeg) then the only part you don't know is the file's name itself.

Does that make sense? Did I miss an important fact somewhere in there?

After all that, you've now presumably come to the conclusion that all you need in the database table is the plain name, meaning like "610f1962cc3621.48842272.jpeg". So

1. Fix your file uploading code to only store that part of the filename.
2. Whenever you need an <img> reference to that file, have the src be the public path to the upload directory + the filename from the database. If the upload directory is /opt/lampp/htdocs/qcic/newsnet/img/posts and your website is at /opt/lampp/htdocs then the public path is /qcic/newsnet/img/posts.

That's all it takes.

Link to comment
Share on other sites

ahh, bro, thank you so much. That was driving me crazy, and it makes so much more sense now. I was simply passing the wrong variable into the database.

I simply had to change this ->

$post_obj->addNews(
            $_POST['title'], $_POST['content'], $_POST['category'], 
            $_POST['status'], $_POST['post_type'], $_POST['tags'], $target_file
        );

to this ->

$post_obj->addNews(
            $_POST['title'], $_POST['content'], $_POST['category'], 
            $_POST['status'], $_POST['post_type'], $_POST['tags'], basename($file_new_name)
        );

The last database parameter. and then add 'img/posts/' before the $image call in the HTML, obviously.

But thinking of it the way you said helped and makes total sense. Thanks again

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.