jploch

[SOLVED] 403 Forbidden when loading images from folder

Recommended Posts

Hi folks!

For a website Iam working on I need to (pre)load a huge amount of images (100-500) from a folder in assets (wich I upload via FTP).

To preload them I want to add them to the DOM inside a container, that I hide with css.
This images will be use for a frame by frame animation (that animates with scrolling) so they should be loaded parallel and if the user clicks a cancel button, the loading should be canceled. (My website is using ajax to load pages with different animations, and the loading of the second animation waits till the loading of the first animation is loaded completly, wich I want to prevent). 

I want to use ajax to do this, so I can cancel the loading with xhr.abort();

Here is my code:

var folder = '{$config->urls->assets}sequenzen/test/';

xhr = $.ajax({
    url : folder,
    success: function (data) {
        $(data).find("a").attr("href", function (i, val) {
            if( val.match(/\.(jpe?g|png|gif)$/) ) { 
                $(".preloader").append( "<img src='"+ folder + val +"'>" );
            } 
        });
    }
});

this will give me a 403 forbidden error.
After some research I found out that I have to put a .htaccess in my assets folder.
I also tried putting it in the sub folder "test", where the files are, but Iam still getting the error.

Is there anything else Iam missing? Is there a configuration in PW i have to change to do that?

Share this post


Link to post
Share on other sites

PW blocks direct access to PHP files within /site/

Alternatives are to place your PHP file outside of /site/ (e.g. in the root directory) or to use a PW template/page to respond to your AJAX request. The latter would be nice solution in this case because you could use an images field in the template to hold your animation images.

  • Like 2

Share this post


Link to post
Share on other sites

thx! I put the files in the template folder and still get a 403.
With commenting the following line in .htaccess (in root) it works:


Block access to any PHP or markup files in /site/templates/

# RewriteCond %{REQUEST_URI} (^|/)(site|site-[^/]+)/templates($|/|/.*\.(php|html?|tpl|inc))$ [OR]

are there any security risks in doing this?

Share this post


Link to post
Share on other sites
5 minutes ago, jploch said:

thx! I put the files in the template folder and still get a 403.

The templates folder is at /site/templates/, so it's still within /site/.

I don't recommend changing any of the security restrictions in the PW htaccess file.

  • Like 1

Share this post


Link to post
Share on other sites

Because of the huge amount of images I used a file Field on a page to store the images, which is working nicely!
Now I only have the problem that I want to sort the files alphabetically/numerical.
My files are named like this: 

file_0.jpg
file_1.jpg
file_2.jpg


I have this wich is not working:

$sortetFiles = $item->sequenz_files->sort('name');
       foreach ($sortetFiles as $key => $file) {   
   echo "<img src='{$file->url}'>";
}

 

Share this post


Link to post
Share on other sites
31 minutes ago, jploch said:

I have this wich is not working

Not working in what way? Your files are listed but in the wrong order? It looks like it should work.

2017-11-14_123531.png.31868c3ccd50057aab5586ca4d8e55d1.png

Share this post


Link to post
Share on other sites

sorry for the late response.

Iam still struggling with the sort order.
With this the images are in the wrong order:

$sortetFiles = $item->sequenz_files->sort('name');
       foreach ($sortetFiles as $key => $file) {   
   echo "<img src='{$file->url}'>";
}


Output:

<img src='0.jpg'>
<img src='1.jpg'>
<img src='10.jpg'>
<img src='100.jpg'>
<img src='101.jpg'>
<img src='102.jpg'>
.....

maybe I need to rename the Images, like 000, 001, 002, etc.?

Share this post


Link to post
Share on other sites
7 hours ago, jploch said:

maybe I need to rename the Images, like 000, 001, 002, etc.?

If you can control the naming of the images then that is an easy solution.

Otherwise you need to do natural sorting of the files array. Something like:

$files_array = $item->sequenz_files->getArray();
natsort($files_array);
// Now foreach $files_array

// And if you need the files as a Pagefiles object for some reason
$pagefiles = new Pagefiles($item);
$pagefiles->import($files_array);
// Now foreach $pagefiles

 

  • Like 2

Share this post


Link to post
Share on other sites

This takes me back to my newbie days :)

 

PS - hope that didn't come across as though I was suggesting that is a newbie question @jploch - I would probably have referred to that old thread if I had the need once again.

  • Like 3

Share this post


Link to post
Share on other sites

thanks Robin and Adrian!!
Robins solution worked for me.

Here is my final Code, with loading and sorting the files and converting them to an PageImage so that I can resize them later (if needed) :)
This Example also uses lazysizes to load the images. Maybe this helps someone:

$files_array = $item->sequenz_files->getArray();
natsort($files_array);

// And if you need the files as a Pagefiles object for some reason
$pagefiles = new Pagefiles($item);
$pagefiles->import($files_array);
// Now foreach $pagefiles
        $si = 0;
       foreach ($pagefiles as $imagefile) {
         if($imagefile->ext == 'jpg'){
         $si++;
// create a new Pageimage with the file
        $preloaderImage = new Pageimage($item->images, $imagefile->filename);
        echo "<img src='data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==' data-src='{$preloaderImage->url}' class='{$si} lazyload' />";
    }
       
}

 

  • Like 2

Share this post


Link to post
Share on other sites
On 17.11.2017 at 9:37 PM, adrian said:

PS - hope that didn't come across as though I was suggesting that is a newbie question @jploch - I would probably have referred to that old thread if I had the need once again.

no offense taken! But Iam a newbie when it comes to PHP tbh. :)   

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now


  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By rushy
      Has anyone used pagination with ajax driven content? I'm using the MarkupPagerNav module to give me pagination, but my content is updated by an ajax post to refresh the body content of a table. The pagination links show a myproject/http404/?page=n for each link generated so they give a 404 page not found. I believe this is because the file containing my ajax code resides in the root of my project as a "web service" and does not have the access it needs, but I'm unsure really.
      If anyone can throw any light on this I would be very grateful. I include the code with my ajax below.
      <?php namespace ProcessWire; require_once ('./index.php'); // bootstrap ProcessWire if($config->ajax) { $pg = $pages->get("/single-use-carrier-bags/"); $selector = wire('input')->post('selector'); $mytableContent = ''; // hold the table markup // $retailer = $pg->children($selector); // for info. only $selector looks like this -> $retailer = $pg->children("sort=title, include=all, limit=10"); $pageinate = $retailer->renderPager(); echo $pageinate; foreach ($retailer as $r) { $mytableContent .= "<tr> <td><a href= '$r->url' target='_blank'>$r->title</a></td> <td>$r->category</td> <td>".numFormat($r->no_bags_issued)."</td> <td>".numFormat($r->gross_proceeds)."</td> <td>".numFormat($r->net_proceeds)."</td> <td>$r->other_use_net_proceeds</td> <td>".numFormat($r->amount_donated)."</td> <td>$r->good_causes_in_receipt</td> <td>".numFormat($r->no_paper_bags_issued)."</td> <td>".numFormat($r->no_bags_for_life)."</td> </tr>"; } echo $mytableContent; } ?>  
    • By rushy
      I have a table in my template that I  would like to update using Ajax when a button is pressed. I am not sure how to go about this and hope somebody here could point me in the right direction. Here is my code for the table output. You can see I loop through the fields to output using a hard wired selector to list the retailer type. I have a button for Supermarkets that fires a js handler myFunc and I need to put the ajax there to call this page again with a param so I can then form the selector for supermarkets and update the table. When I get this working and understand how to do it in ajax I will code up a selector that is formed dependant on a bank of buttons and the table will update without the rest of the page - like magic! That's what ajax is for right?!
      Thanks for any help - Paul
      <button type="button" onclick="myFunc()" value="1" class="btn btn-primary">Supermarkets</button> <div class= "table-responsive"> <table class="table table-hover table-striped"> <thead> <tr> <th>Retailer</th> <th>No. bags issued</th> <th>Gross proceeds £</th> <th>Net proceeds £</th> <th>Other use of net proceeds</th> <th>Amount donated £</th> <th>Good causes in receipt of proceed</th> <th>No. of paper bags issued</th> <th>No. of bags for life</th> </tr> </thead> <tbody> <?php $pg = $pages->get("/single-use-carrier-bags/"); $retailer = $pg->find("category=DIY, sort=title, include=all"); foreach ($retailer as $r) { echo "<tr> <td><a href= '$r->url'>$r->title</a></td> <td>".numFormat($r->no_bags_issued)."</td> <td>".numFormat($r->gross_proceeds)."</td> <td>".numFormat($r->net_proceeds)."</td> <td>$r->other_use_net_proceeds</td> <td>".numFormat($r->amount_donated)."</td> <td>$r->good_causes_in_receipt</td> <td>".numFormat($r->no_paper_bags_issued)."</td> <td>".numFormat($r->no_bags_for_life)."</td> </tr>"; } ?> </tbody> </table> </div> </div> </div> <script type="text/javascript"> function myFunc() { } </script>  
    • By entschleunigung
      hello,
      i have a _func.php file with this function. in the documentation i read that some api variables in functions are not available, so i use wire('pages').
      function doSomething($u, $p) {     $p = wire('pages')->get("id=$p");     $u = wire('pages')->get("id=$u");     $p->of(false);     { ... populate repeater field stuff }     $p->save(); } if i call this function in my home.php like doSomething(41,1093) (only for testing!) everything is fine, the function works, it add items to a repeater field.
       
      the german says "Wenn es dem Esel zu wohl ist, geht er aufs Eis", so i play around with ajax to fire up this function. 
      $(document).ready(function() { $("#hit").click(function(){ $.ajax({ url: '<?= $config->urls->templates?>includes/_func.php/', type: 'post', data: {userID: "<?= $user->id ?>", pageID: "<?= $page->id ?>"}, success: function(output){ console.log(output); } }) }) })  
      i read something about variable scopes and i think i understand it a little bit. but i don't understand why doSomething(41,1093)  works in home.php the ajax call runs into a Call to undefined function wire() ?   also i tried if ($config->ajax) but no luck ...
      that's the relevant party of  _func.php. 
      function doSomething($u, $p) {     $p = wire('pages')->get("id=$p");     $u = wire('pages')->get("id=$u");     $p->of(false);     { ... populate repeater field stuff }     $p->save(); } if(isset($_POST['userID']) && !empty($_POST['userID']) && isset($_POST['pageID']) && !empty($_POST['pageID'])) { $u = $_POST['userID']; $p = $_POST['pageID']; { ... } echo sendLike($u, $p); }  
      where is my mistake? any ideas? 
       
      thx
       
    • By celfred
      Hello,
      I'm desperately trying to update my website to PW 3.0.62 and I'm facing issues to to module compatibility. I was stuck with Pages2Pdf which I managed to solve bu updating the module from Github, but now it's the Pages Web Service module... and this time, I don't know wht to do
      The Module is found there. But it is quite old and I can't find it in the modules catalogue... and my site is making quite a use of it (I can't think of a way to do otherwise, sorry...)
      After adding the FileCompiler=0 to the module pages, the error I'm stuck with is :
      Fatal error: Class 'WireData' not found in /home/celfred/PlanetAlert/site/modules/ServicePages/ServicePages.module on line 22
      and I have no idea on what to do... I must admit I'm not a programmer but a middle-school teacher... (for your information, here's the site I'm talking about : http://planetalert.tuxfamily.org ) but I'm struggling hard to solve the different issues I have to face and I'm wlling to understand things. I have just spent many hours trying to make 2.8 work on my localhost (and it seems ok ) but I'd like to switch to 3.x to prepare the future
      If anyone had the will to spend a few minutes to try and help me, I would greatly appreciate.
      Thanks in advance !
      If you need more information to understand my problem, feel free to ask.
    • By hellomoto
      I want to implement tables with Dynatable populated via ajax. Here's what I could muster:
      if($config->ajax) { $results = $pages->find($sanitizer->selector()); foreach($results as $r) $array[] = [ $r->title, $r->modified ]; header("Content-type: application/json"); echo json_encode($array); exit; } $content .= <<<EOT <table id="my-ajax-table"></table> <script> $("#my-ajax-table").dynatable({ dataset: { ajax: true, ajaxUrl: '.', ajaxOnLoad: true, records: [] } }); </script> EOT; But that's really nothing. Pro tips?