Search code examples
javascriptreactjsfile-uploaduploadsubdirectory

How to upload folders to react with special characters in the name


I have a problem with my javascript uploading: I am using this code:

const handleParameterSearchUpload = async (event) => {
    const files = event.target.files;
    console.log(files);
    const folders = {};

    for (let i = 0; i < files.length; i++) {
      const file = files[i];
      const filePath = file.webkitRelativePath;
      const pathParts = filePath.split('/');

      // If the file is in a subfolder, add the file to the folder's list
      if (pathParts.length > 2) {
        const folderName = encodeURIComponent(pathParts[1]);
        if (!folders[folderName]) {
          folders[folderName] = [];
        }
        folders[folderName].push(file);
      }
    }
    console.log(folders.length);
    // Call processFiles for each folder
    for (const folderName in folders) {
      const folderFiles = folders[folderName];
      await processFiles(folderFiles, true);
      console.log("Processed", folderName);
    }
    parameterSearchInputRef.current.value = "";
  };

to process the files in a folder.

This code is used here:

<input
  type="file"
  webkitdirectory="true"
  style={{ display: 'none' }
  ref={parameterSearchInputRef} 
  onChange={handleParameterSearchUpload} 
/>

Now in this folder there are files and subfolders which are not empty. Unfortunately I have a problem. When I upload the folder the files are uploaded, but not the subfolders. The code is not the problem, because when I rename the folder it works fine, but with this folder name which I upload:

20240118-165159[param.defaults]CombinationParamSearch{sheets.l4_cortex_inh.params.cell.params.v_thresh_[-57.5, -58],sheets.l4_cortex_exc.AfferentConnection.base_weight_[0.0013, 0.0016, 0.0018]}

it doesn't work.

Unfortunately I will always upload these types of folders to the webpage, how to resolve the issue? The subfolders have the following name: SelfSustainedPushPull_ParameterSearch_____base_weight_0.0013_v_thresh_-57.5 SelfSustainedPushPull_ParameterSearch_____base_weight_0.0013_v_thresh_-58

and so on

Unfortunately the base problem is that the subfolders seem like are not getting uploaded, because if I log the console, the subfolders nor the contents inside them are not getting logged. I really don't know how to resolve this issue, without using packages like fs or path. Any ideas? Unfortunately I can't just ask the users to rename the folders, because these folder names are generated from another software.


Solution

  • As far as I know React does not like webkitdirectory and also webkitdirectory might as well be soon deprecated in favor of dropzones. Not really sure about this, but that's what I've read in some discussions about it. Also, I don't think it is fully compatible with all browsers. See browser compatibility.

    For file uploads with directories and subdirectories, it's often more effective to use the standard 'HTML File API' in combination with DirectoryReader. Another thing to consider is recursively traversing the directory structure.

    Here's an example on how you can implement it:

    const handleParameterSearchUpload = async (event) => {
      const traverseFiles = async (files) => {
        for (let i = 0; i < files.length; i++) {
          const file = files[i];
          if (file.isDirectory) {
            const directoryReader = file.createReader();
            const entries = await new Promise((resolve) => {
              directoryReader.readEntries(resolve);
            });
            await traverseFiles(entries);
          } else {
            // Process the file
            console.log("Uploading file:", file.name);
            // Upload logic
        }
      };
    
      const files = event.target.files;
      console.log("Uploaded files:", files);
    
      await traverseFiles(files);
    
      // Clear `event.target.value` instead, since we can access the input element
      // directly from the event object. No need for ref.
      event.target.value = "";
    };
    

    Something I also want to mention, just in case, is that you need to use decodeURIComponent to get the original folder name after you encoded it.

    Generally speaking, using FTP or SFTP to upload your files to the server would be an ideal approach for handling folders with multiple subfolders and files. HTTP is not really suited for bulk file transfers. Another solution you might consider is zipping the files before uploading them to the server and then unzipping them on the server side.