Jump to content
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

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.   Paste as plain text instead

  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.


  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By michelangelo
      Hello there,
      I am building my website, which has a dozen projects with 10 images each. Basically, I need a filtering system but built in the most efficient and user-friendly way. You can see below that the images flow sideways so being hidden, JS lazy loading was a good tool, but I just wanted to try AJAX. Is it fit for this purpose or it's more for dynamic content?
       

    • By louisstephens
      I have been messing around with creating pages from ajax requests, and it has gone swimmingly thus far. However, I am really struggling with creating a page and saving an image via ajax. 
      The form:
      <form action="./" role="form" method="post" enctype="multipart/form-data"> <div> <input type="text" id="preview" name="preview" placeholder="Image Title"> </div> <div> <input type="file" id="preview-name" name="preview-name"> </div> <div> <select id="select-tags" name="select-tags"> <?php $tags = $pages->find("template=tag"); ?> <option value="">Select Your Tags</option> <?php foreach ($tags as $tag) : ?> <option value="<?= $tag->name; ?>"><?= $tag->name; ?></option> <?php endforeach; ?> </select> </div> <div> <button type="button" id="submit-preview" name="submit" class="">Upload Images</button> </div> </form>  
      The ajax in my home template:
      $('#submit-preview').click(function(e) { e.preventDefault(); title = $("#preview").val(); image = $("input[name=preview-name]"); console.log(title); console.log(image); data = { title: title, image: image //not sure if this is actually needed }; $.ajax({ type: 'POST', data: data, url: '/development/upload-preview/', success: function(data) { console.log("Woo"); }, error: function(xhr, ajaxOptions, thrownError) { alert(xhr.responseText); } }); }); And finally in my ajax template:
      $imagePath = $config->paths->assets . "files/pdfs/"; //was from an older iteration $title = $sanitizer->text($_POST['title']); $image = $sanitizer->text($_POST['image']); $p = new Page(); $p->template = "preview"; $p->parent = $pages->get("/previews/"); $p->name = $title; $p->title = $title; $p->save(); $p->setOutputFormatting(false); $u = new WireUpload('preview_image'); $u->setMaxFiles(1); $u->setOverwrite(false); $u->setDestinationPath($p->preview_image->path()); $u->setValidExtensions(array('jpg', 'jpeg', 'gif', 'png', 'pdf')); foreach($u->execute() as $filename) { $p->preview_image->add($filename); } $p->save(); I can complete the file upload but just using a simple post to the same page and it it works well, but I was really trying to work out the ajax on this so I could utilize some modals for success on creation (and to keep my templates a little cleaner). When I do run the code I have, a new/blank folder is created under assets, and a new page is created with the correct title entered. However, no image is being processed. I do get a 200 status in my console. I have searched google for help, but everything seems to be slightly off from my needs. If anyone could help point me in the right direction I would greatly appreciate it. 
    • By louisstephens
      So I am using ajax to upload an image, but I am getting the error "Method WireUpload:: save does not exist or is not callable". I am not quite sure how to go about fixing this (at the moment).
      elseif($config->ajax && $input->urlSegment1 == "upload-preview") { $u = $config->paths->assets . "files/pdfs/"; $title = $sanitizer->text($_POST['title']); $p = new Page(); $p->template = "preview"; $p->parent = $pages->get("/previews/"); $p->name = $title; $p->title = $title; $p->save(); $p->setOutputFormatting(false); $u = new WireUpload('preview_image'); $u->setMaxFiles(1); $u->setOverwrite(false); $u->setDestinationPath($p->preview_image->path()); $u->setValidExtensions(array('jpg', 'jpeg', 'gif', 'png', 'pdf')); foreach($u->execute() as $filename) { $p->preview_image->add($filename); } $u->save(); } I compared my code to something I did previously (though previously I just posted to the current template file, not through ajax) which works, but this doesnt seem to be working. I have the _init.php file prepending as well. Does anyone have any ideas of what might be happening?
    • By Brian Scramlin
      I just wanted to share that I added an AJAX-powered gallery to an artist website that I developed and host: https://jackpinecreations.com/gallery/

      There were two things that frustrated me about creating this. Perhaps you can show me a better way.
      1. After creating my processing script, which I placed under /templates/scripts/get-items.php, I realized that I would get a 403, due to ProcessWire's routing and security. This forced me to have to create a template and page for this little script. This was frustrating simply because it seemed unnecessarily confusing. But worse, see #2.
      2. I usually use config.php to prepend and append each of my templates with a head.inc and foot.inc, which keeps my templates easy to use and I don't have to go and use the GUI to do so on each template separately. However, since I realized I needed to create a new template and page so as to access it, whenever I sent POST params to it, I would get the header and footer along with it!!! I could find no workarounds and had to remove the pre/append calls in config.php and use the GUI on each template individually.  
      Code Below if you're interested:
      HTML and JavaScript (forgive my sad JavaScript skills, I know this can be tightened up)
      <!-- Begin Grid --> <div class="container mt-4"> <div id="gallery" class="row"> <?php foreach ($page->children("limit=9") as $child): ?> <div class="col-6 col-md-4 gallery-item"> <a href="<?= $child->url ?>" title="View <?= $child->title ?>"> <img class="gallery-item" src="<?= $child->item_featured_image->size(640, 640)->url ?>" alt="<?= $child->title ?> Image"> </a> </div> <?php endforeach; ?> </div> </div> <!-- End Grid --> <div class="center-block text-center"> <button id="get-more-items" type="button" name="get-more-items" class="btn-vintage">Load More</button> </div> <script type="text/javascript"> var buttonGetItems = document.getElementById("get-more-items"); var indexStart = 0; buttonGetItems.addEventListener("click", function() { indexStart += 9; $.ajax({ url: '<?= $pages->get(1186)->url ?>', type: "POST", dataType:'json', // add json datatype to get json data: ({page_id: <?= $page->id ?>, index_start: indexStart}), success: function(data){ console.log(data); if (data[1]) { //for each element, append it. $.each(data, function(key, value) { $("#gallery").append(value); }); } else { $("#get-more-items").after('<p class="center-block text-center">There are no more items to load.</p>'); $("#get-more-items").remove(); } } }); }); </script> Processing Script
      <?php $items_array = []; $i = 0; foreach ($pages->get($input->post->page_id)->children->slice($input->post->index_start, 9) as $child) { $i++; $items_array[$i] = "<div class='col-6 col-md-4 gallery-item'> <a href='$child->url' title='View $child->title'> <img src='{$child->item_featured_image->size(640,640)->url}' alt='$child->title Image'> </a> </div>"; } echo json_encode($items_array); I love ProcessWire for hundreds of reasons, but I've been using AJAX more and more, and I'm not liking having to create templates to access scripts. 
      Any advice?
    • By celfred
      Hello,
      I'm facing a weird issue here. I have a page loaded with this code inside (my comments in line ends) :

      if ($session->allPlayers) { // Set in a head.inc file. I have also a $session->set('allTeams', $allTeams); in my head.inc   $allPlayers = $session->allPlayers; } else {   $allPlayers = getAllPlayers($user, false);   $session->set('allPlayers', $allPlayers); } bd($session->getAll()); // HERE, I get a number of 11 variables which is what I expect In the same page, I have a link pointing to ajaxContent.php that loads stuff via Ajax.
      I just write this in my ajaxContent.php to test :

      bd($session->getAll()); // HERE, I get only 9 variables. All my newly set $session variables ($allTeams and $allPlayers) are not conveyed to ajaxContent.php ??? Would you have any idea why is that ??? Another thing : I have a $session->headMenu set in my head.inc, and this one works fine. I can retrieve it in my ajaxContent.php page.
      I've tried cleaning all caches but it doesn't change anything 😞 
      At first, I expected it to be a 15-minute update to my site... It turns out to be a 2-hour issue and I'm still  stuck.
      Thanks for your ideas ! 
×
×
  • Create New...