169

My website is serving a lot of pictures from /assets/photos/ folder. How can I get a list of the files in that folder with Javascript?

bevanb
  • 8,201
  • 10
  • 53
  • 90
  • 6
    What have you tried? And in what context do you want to retrieve the list of files... From the browser or from a server with node.js? – David Barker Jul 07 '15 at 16:29
  • 1
    And which browser/s you are supporting? – SK. Jul 07 '15 at 16:31
  • @Mike this is just for the latest version of Chrome – bevanb Jul 07 '15 at 16:35
  • 1
    @Mike I doubt the browser choice really matters. The browser doesn't have access to the list of files unless the server presents it. – Mike Cluck Jul 07 '15 at 16:35
  • @MikeC ya you are right. I was thinking about IE `ActiveXObject` to access client system filesystem. So I asked. – SK. Jul 07 '15 at 16:37
  • 1
    possible duplicate of [best way to get folder and file list in Javascript](http://stackoverflow.com/questions/20822273/best-way-to-get-folder-and-file-list-in-javascript) – SK. Jul 07 '15 at 16:40
  • I am using laravel 5, how can i retrieve images name from folder using javascript or jquery? – 151291 Feb 17 '17 at 12:30

13 Answers13

181

The current code will give a list of all files in a folder, assuming it's on the server side you want to list all files:

var fs = require('fs');
var files = fs.readdirSync('/assets/photos/');
Christoffer Karlsson
  • 4,539
  • 3
  • 23
  • 36
  • 23
    I meant accessing a list of files from the client, sorry wasn't more clear. – bevanb Jul 07 '15 at 16:37
  • 15
    Where does require() come from or is defined??? Your code proiduces a "'require' is not defined" error. Have you tested your code? If so, have you maybe missed some important part referring to 'require'? – Apostolos Jun 14 '18 at 09:52
  • 11
    @Apostolos As OP notes in the description, this needs to be server-side code. You can not run this in a browser. Running this script with Node.js does not throw any errors. – Naltroc Aug 24 '18 at 20:25
  • 4
    This is a good way but seems doesn't answer the question directly. The simple answer is No, in JS from client side(browser) there is no direct way to get list of files in a folder/directory on server side. – Akshay Hiremath May 06 '19 at 18:55
  • 4
    require() is only supported with nodejs – Dulmina Mar 09 '20 at 10:26
  • This top rated answer is one very specific to back-end, which is not what most people mean when they say javascript. – Cybernetic Oct 23 '21 at 15:45
  • @Apostolos I found this video to be helpful in understanding the basics about NodeJS: https://www.youtube.com/watch?v=pU9Q6oiQNd0 – WhyWhat May 15 '22 at 08:47
  • Thanks @WhyWhat. I hate to use Youtube for things requiring short explanations. I wonder who doesn't! Anyway, it's a 5-years-ago question ... Thanks, anyway! – Apostolos May 16 '22 at 08:51
49

No, Javascript doesn't have access to the filesystem. Server side Javascript is a whole different story but I guess you don't mean that.

SK.
  • 4,174
  • 4
  • 30
  • 48
14

I write a file dir.php

var files = <?php $out = array();
foreach (glob('file/*.html') as $filename) {
    $p = pathinfo($filename);
    $out[] = $p['filename'];
}
echo json_encode($out); ?>;

In your script add:

<script src='dir.php'></script>

and use the files[] array

IfThenElse
  • 485
  • 5
  • 13
12

For getting the list of filenames in a specified folder, you can use:

fs.readdir(directory_path, callback_function)

This will return a list which you can parse by simple list indexing like file[0],file[1], etc.

double-beep
  • 5,031
  • 17
  • 33
  • 41
Ahmad Zafar
  • 131
  • 1
  • 4
10

For client side files, you cannot get a list of files in a user's local directory.

If the user has provided uploaded files, you can access them via their input element.

<input type="file" name="client-file" id="get-files" multiple />


<script>
var inp = document.getElementById("get-files");
// Access and handle the files 

for (i = 0; i < inp.files.length; i++) {
    let file = inp.files[i];
    // do things with file
}
</script>
Naltroc
  • 989
  • 1
  • 14
  • 34
3

I use the following (stripped-down code) in Firefox 69.0 (on Ubuntu) to read a directory and show the image as part of a digital photo frame. The page is made in HTML, CSS, and JavaScript, and it is located on the same machine where I run the browser. The images are located on the same machine as well, so there is no viewing from "outside".

var directory = <path>;
var xmlHttp = new XMLHttpRequest();
xmlHttp.open('GET', directory, false); // false for synchronous request
xmlHttp.send(null);
var ret = xmlHttp.responseText;
var fileList = ret.split('\n');
for (i = 0; i < fileList.length; i++) {
    var fileinfo = fileList[i].split(' ');
    if (fileinfo[0] == '201:') {
        document.write(fileinfo[1] + "<br>");
        document.write('<img src=\"' + directory + fileinfo[1] + '\"/>');
    }
}

This requires the policy security.fileuri.strict_origin_policy to be disabled. This means it might not be a solution you want to use. In my case I deemed it ok.

2540625
  • 11,022
  • 8
  • 52
  • 58
  • Is this supposed to work with other browsers? – KcFnMi Sep 14 '22 at 01:20
  • Well, I think it should work, but I haven't tested this on other browsers, and since it kind of gets rid of some safety stuff I don't know if other browsers have similar switches in the settings. It wouldn't surprise me if todays browsers won't allow stuff like this any more. – pietervanderstar Sep 16 '22 at 05:54
3

I made a different route for every file in a particular directory. Therefore, going to that path meant opening that file.

function getroutes(list){
list.forEach(function(element) {
  app.get("/"+ element,  function(req, res) {
    res.sendFile(__dirname + "/public/extracted/" + element);
  });
});

I called this function passing the list of filename in the directory __dirname/public/extracted and it created a different route for each filename which I was able to render on server side.

1

If you use nginx, you can set autoindex on, then you request url, you can get the file names from response.

<script>
  function loadDoc() {
    var xhttp = new XMLHttpRequest();
    xhttp.onreadystatechange = function () {
      if (this.readyState == 4 && this.status == 200) {
        myFunction(this);
      }
    };
    xhttp.open("GET", "/assets/photos/", true);
    xhttp.send();
  }

  function myFunction(xml) {
    // console.log(xml.responseText)
    var parser = new DOMParser();
    var htmlDoc = parser.parseFromString(xml.responseText, 'text/html');
    var preList = htmlDoc.getElementsByTagName("pre")[0].getElementsByTagName("a")
    for (i = 1; i < preList.length; i++) {
      console.log(preList[i].innerHTML)
    }
  }
</script>
0

To then check for a specific file, you can do parsedDirectory.includes("filename") and it will return a boolean value.

0

As others' answers suggest it seems impossible on client side, so I solved it on server side as following: Client side by js

get_file(conf.data_address).then(imgs => { // get_file is wrapper of fetch API
    let img = new Image();
    img.src = `./files/Blackpink/${imgs[0]}`; // e.g. load the first img 
    img.height = 40;
    return new Promise(resolve => {
      img.onload = () => {
        resolve(img);
      }
    })
  })

Server side by django:

def get(self, request): # get method
        address = request.query_params.get('address') # get the requested folder
        is_database = request.query_params.get('is_database')
        if address.endswith('/'):
            j = u.get_path_files(address,is_full=False) # wrapper of os.listdir of python to get the files in the requested directory.
Youth overturn
  • 341
  • 5
  • 7
0

While the OP makes it sound like Node.JS/Server Side, a comment later states he is looking for client side. Regardless, Server Side is already covered by other answers.

Many state it isn't possible client side, but there are in fact 2x methods as described below.

Note: Client Side will ALWAYS require user input, IE: Open File Dialog and user selects Folder, then Browser prompts "Are you Sure Y/N".

I went with this method as it does NOT require HTTPS and works in IE. Note: While it "works" in IE, it only allows selecting a single file in IE, it requires Edge/Chrome to select a folder.

HTML:

Styling an input type="file" button

<label for="file-upload" class="ms-Button ms-Button--primary">
    <span class="ms-Button-label">LIST FILES IN DIR</span>
    <span class="ms-Button-description">List Files In Directory</span>
</label>
<input id="file-upload" type="file" webkitdirectory="" directory="" hidden />

JS:

let i = document.querySelector('input').addEventListener('change', (e) => {
    var Arr_Of_Objs = []
    for (let i = 0; i < e.target.files.length; i++) {
        var file_name = e.target.files[i].name
        var obj = {}
        obj["Files"] = file_name
        Arr_Of_Objs.push(obj);
        console.log(e.target.files[i].name);
    }
    Button_LIST_FILES_OnClick(Arr_Of_Objs)
})

https://stackoverflow.com/a/49657412/5079799

A more modern approach would be using showDirectoryPicker but it has limited browser compatibility and REQUIRES HTTPS.

https://developer.mozilla.org/en-US/docs/Web/API/Window/showDirectoryPicker#browser_compatibility

Uncaught (in promise) TypeError: window.showOpenFilePicker is not a function

https://stackoverflow.com/a/72687727/5079799

JS:

const button = document.getElementById('button');
button.addEventListener('click', async () => {
  const dirHandle = await window.showDirectoryPicker();
  for await (const entry of dirHandle.values()) {
    console.log(entry.kind, entry.name);
  }
});
FreeSoftwareServers
  • 2,271
  • 1
  • 33
  • 57
-2

Applying JSONP to IfTheElse answer:

In /dir.php write the following:

<?php
    $out = array();
    foreach (glob('file/*.html') as $filename) {
        $p = pathinfo($filename);
        $out[] = $p['filename'];
    }
    echo 'callback(' . json_encode($out) . ')';
?>

In your index.html add this script:

<script>
    /* this function will be fired when there are files
       in dir search in php' glob
     */
    function callback(files) {
        alert(files);
     }

    /* call inside document.ready to make sure the
       callback is already loaded
     */
    $(document).ready(function() {
        let php = document.createElement("script");
        php.setAttribute("src", "/dir.php");
        document.body.appendChild(php);
    });
</script>
Carlos Barcellos
  • 544
  • 1
  • 4
  • 10
-2

I understand that the problem is old but still comes back in many issues. It's true that on client side you can't list files in a local directory using pure JavaScript. Below is a complete snippet that uses PHP and transfers the file list with extensions to JavaScript.

<?PHP
  $out = array(); 
  $out = scandir("MT940");      // Or any path to local dir to be listed
  $out = array_diff($out, array('.', '..'));    // Skip current and parent dir 
?>

<!DOCTYPE html>
<html lang="pl-PL">
<head>
  <meta charset="UTF-8" />
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <script src='https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js'></script>  
  <title></title>
</head>
<body>
  <div class="service-container"        
    data-files= '<?php echo (json_encode($out)); ?>'>   
  </div>
  <script>
    let files;     
    $(document).ready(function() {
      $('.service-container').each(function() {
        let container = $(this);
          files = container.data('files');
          fileNames = Object.values(files);
      });
    });
  </script> 
  
  <!-- Some HTML code here -->
  
  <script>
    let fileNames = [];
    $(document).ready(function() {
      console.log(fileNames);
      // Do something with fileNames
    });
  </script>
</body>
</html>
AndyPL
  • 11