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

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 gebeer
      Hello all,
      wasn't sure where to put this, so it goes in General section.
      Ryan shows a hook that we can use to mirror files on demand from live server to development environment to be up to date with the files on the server without having to download complete site/assets/files folder.
      I just implemented this but had problems getting files to load from a site in development that is secured with user/password via htaccess.
      First I tried to use WireHttp setHeader method for basic authentication like this
      function mirrorFilesfromLiveServer(HookEvent $event) { $config = $event->wire('config'); $file = $event->return; if ($event->method == 'url') { // convert url to disk path $file = $config->paths->root . substr($file, strlen($config->urls->root)); } if (!file_exists($file)) { // download file from source if it doesn't exist here $src = 'http://mydomain.com/site/assets/files/'; $url = str_replace($config->paths->files, $src, $file); $http = new WireHttp(); // basic authentication $u = 'myuser'; $pw = 'mypassword'; $http->setHeader('Authorization: Basic', base64_encode("$u:$pw")); $http->download($url, $file); } } But, unfortunately this didn't work.
      So now I am using curl to do the download. My hook function now looks like this
      function mirrorFilesfromLiveServer(HookEvent $event) { $config = $event->wire('config'); $file = $event->return; if ($event->method == 'url') { // convert url to disk path $file = $config->paths->root . substr($file, strlen($config->urls->root)); } if (!file_exists($file)) { // download file from source if it doesn't exist here $src = 'http://mydomain.com/site/assets/files/'; $fp = fopen($file, 'w+'); // init file pointer $url = str_replace($config->paths->files, $src, $file); $u = 'myuser'; $pw = 'mypassword'; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_TIMEOUT, 50); // crazy high timeout just in case there are very large files curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_USERPWD, "$u:$pw"); // authentication curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); // authentication curl_setopt($ch, CURLOPT_FILE, $fp); // give curl the file pointer so that it can write to it curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); $data = curl_exec($ch); curl_close($ch); } } Now I can load files and images from the htaccess protected development server 🙂
      If anyone knows how to get this to work with WireHttp, please let me know. Thank you.
    • By ICF Church
      Hi 👋
      Anyone else having this problem?
      Requirements:
      - Repeater (matrix & normal) with mutlilanguage fields (text, textarea…) 
      - Backend language set to something other than default (ie. German) 
      Reproduce:
      - Add a new repeater Item (ajax, I found no way to possible to disable it with matrix)

      (Notice how the default language tab is active instead of the backend language…)
      - Write something into the (default language) field
      - Try to save, if field is required, this will not work. If not required, then when reloading, the content will be inside the backend language field, instead of the default language field who was (presumably) active
      Analysis:
      When  loading  a new repeater element with ajax, the default langue tab is active, but the backend language inputfield is visible (with no visual indication). When writing into the field, it will populate the backend language. When manually clicking on the default language tab (which is already active), the field will switch to the actual default language field (which is [now] empty) (that can now be populated…)
      Also Notice, the labels of the elements to be added are in default language as well instead of the translated label (images instead of Bilder)…
      ProcessWire 3.0.148, Profields 0.0.5…
      Is it my system configuration, or does anyone else have the same issue? This is a screen recording of the problem:

      Screen Recording 2020-02-25 at 14.18.31.mov
    • 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?
×
×
  • Create New...