Acquiring exclusive files from Laravel 8 storage directory using JavaScript

I find myself in a specific situation:

  • Working with a Laravel 8 application.
  • My users upload STL files, which are stored in the storage/app/users/{userid} directory.
  • These STL files are private and not accessible to everyone as they are not located in the public folder.

Now, I am attempting to access these private STL files using JavaScript in order to display them in my Three.js scene for viewing.

However, when trying to retrieve the file path from the database before and passing it to the Three.js STLLoader function like this:

import * as THREE from 'three';
import { STLLoader } from 'three/examples/jsm/loaders/STLLoader.js';

// {...}
let THREE_loader = new STLLoader();
let THREE_geometry;

THREE_loader.load(filePath, function (geometry) {
    THREE_geometry = geometry;

    // {...}
});

I encountered the 404 error message every time I attempt it, since the provided path is relative to the web root and incorrect!

[Error] Failed to load resource: the server responded with a status of 404 (Not Found)

So, my question now is:

Is there a way to overcome this obstacle? How can I access private files (not in the public folder) through JavaScript in my Laravel 8 application? There must be a solution, right?


Some other solutions I considered:

  • Directly storing the files in the database -> files may be too large?!
  • Storing an "secure" encrypted file path within the public(!) directory in the database -> not secure enough?!

Both of these "solutions" are definitely not ideal for me!


If anyone could provide guidance or direction on this matter, I would greatly appreciate it! 🤔

Warm regards, Leon

Answer â„–1

My Journey to Finding the Solution:


In General:

After much deliberation, I realized that to access private files, there must be a special web route with a corresponding FileController that checks for permission to view the file. It then either aborts or returns the file using a FileResponse.


In Laravel (in my case):

JavaScript

import * as THREE from 'three';
import { STLLoader } from 'three/examples/jsm/loaders/STLLoader.js';

let THREE_loader = new STLLoader();
let THREE_geometry;

THREE_loader.load('data/users/1/filename.stl', function (geometry) {
  THREE_geometry = geometry;

  // {...}
});

PHP (Web Route)

<?php

use App\Http\Controllers\File\FileController;
use Illuminate\Support\Facades\Route;

Route::get('data/users/{user_id}/{filename}', [FileController::class, 'load_user_stl']);

PHP (FileController)

<?php

namespace App\Http\Controllers\File;

use App\Http\Controllers\Controller;
use Illuminate\Contracts\Filesystem\FileNotFoundException;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Gate;
use Illuminate\Support\Facades\Response;

class FileController extends Controller
{
    public function load_user_stl($user_id, $filename): \Illuminate\Http\Response
    {
        if (str_contains($filename, '.stl')) {
            if (Gate::allows('access-user-stl') || Auth::id() == $user_id) {
                return $this->return_user_stl($user_id, $filename);
            } else {
                abort(403);
            }
        } else {
            abort(400);
        }
    }

    public function return_user_stl($user_id, $filename): \Illuminate\Http\Response
    {
        $path = storage_path('app/data/users/'.$user_id.'/'.$filename);

        try {
            $file = File::get($path);
            $type = File::mimeType($path);
            $response = Response::make($file);
            $response->header('Content-Type', $type);

            return $response;
        } catch (FileNotFoundException) {
            abort(404);
        }
    }
}

I hope this explanation helps someone out there, and if you have a cleaner solution, please share it with me:)

Leon

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

When trying to access the same path, useEffect does not trigger

I integrated the API to execute when the screen is loaded using useEffect in Next.js v10. The code implementation is straightforward: ... const fetchAPI = async () => { try { await axios.get({ .... }) } catch (e) { console.error(e) } } R ...

The dynamic functionality of the Bootstrap React Modal Component seems to be malfunctioning

I'm encountering an issue with React Bootstrap. I'm using the map function in JavaScript to iterate through admins. While all values outside the modal display correctly from the admins array, inside the modal only one standard object from the arr ...

Encountering an error with Angular-NG8001 due to an unknown element. Any suggestions on how

I am encountering an issue with my Angular project. The project structure I am working with can be found here: app structure. Within my app.module.ts file, the code appears as follows: import { NgModule } from '@angular/core'; import { BrowserMod ...

Tips for integrating Server-Side Rendering into an already established React.js app running on Express.js

I am currently working on a React application and I am looking to add SSR using Express.js. Initially, I made a mistake by creating a repository with just a frontend folder containing the entire React app with typescript, babel, and webpack configurations ...

What is the best approach for writing a concise Select statement that produces a data list?

Currently, I am working on a small web application using Express.js and SQLite for local use. However, I am facing an issue when trying to perform a full select query on a table. All my scripts are written in JScript in 'use-strict' mode. I am a ...

Creating a Breeze js entity using a JSON string and importing it into the breeze cache: A step-by-step guide

Currently, I am developing a mobile single page website that utilizes technologies like breeze js, angular js, web API, and entity framework. To enhance the performance of the site, I have decided to include the breeze metadata in a bundled JavaScript fil ...

Implement a dispatcher in raw JavaScript using React combined with the Redux Toolkit package

In my React app, I have been using Redux and Redux Toolkit within React components by utilizing the useDispatch and useSelector hooks. However, I now need to update the Redux store from a pure JavaScript module that interacts with IndexedDB to save user da ...

An effective method for appending data to a multidimensional array in Google script

Is there a way to expand a multidimensional array of unknown size without relying on a Google Sheets spreadsheet to manage the data? I've searched everywhere but can't find an example for a 3-dimensional array. Here's the challenge I'm ...

Add fresh material to the bottom of the page using Javascript

Hey there, I'm having a bit of trouble with my page where users can post their status. I want the new posts to appear at the bottom after the older posts when the user presses the button. Currently, Ajax is placing all new posts at the top of the old ...

Root scope digest trigger delay

When invoking $scope.$apply() ten times consecutively, it is expected that ten root scope digests will occur. If the call to $scope.$apply() is debounced so that the trailing call always completes, can we assume that the final state of the application rem ...

Tips on adding to Jquery html code while maintaining the current CSS styling

My JavaScript function looks like this: function appendAllQna(qnaList, num){ for (var i in qnaList){ var qnaCom = ""; qnaCom += "<div class='scomment scommentLine'>"; if(qnaList[i].sellerYn == "Y"){ ...

Load grid data only when the tab is clicked in ExtJS

Our app features a dynamic grid loaded with multiple tabs, each containing one or more grids. The issue currently is that when the application loads, it automatically calls all the URLs instead of waiting for the user to click on a tab. We want to optimi ...

Selector that targets an attribute in the beginning of its value [name^=value]

When trying to match input fields by name, I encountered a challenge. The names consist of a base name plus square brackets, which the PHP interpreter converts into arrays. According to the jQuery API, the suggested selector is as follows: ":input[name^=f ...

Is there a way to interact with a DOM element through clicking and then pass it as a variable using PHP?

Is there a way to configure a table so that data from a specific row is sent to a PHP script and displayed in a section on the website when the user clicks on that row? I am looking to pre-fill a data entry form with information from a selected row, allow ...

how can I transfer model values to a dashboard in Rails 5?

I have developed an app that includes an adminlte dashboard. The dashboard is populated with various values obtained by a jQuery file. I am trying to pass module values to the dashboard. For example, the number of users shown in the dashboard should be fet ...

What is a superior option to converting to a promise?

Imagine I am creating a function like the one below: async function foo(axe: Axe): Promise<Sword> { // ... } This function is designed to be utilized in this manner: async function bar() { // acquire an axe somehow ... const sword = await foo ...

What is the best way to execute a series of asynchronous JavaScript functions one after the other?

As I attempt to call the following functions in succession, their return does not always happen in the expected order. Upon discovering asynchronous functions and the concept of using "callbacks," I realized there might be a solution for executing these f ...

Tips for refreshing extensive JSON structures?

I receive product data from the server in JSON format, containing properties and nested arrays up to 4 levels deep. In the frontend, users can update values within these nested structures. Should I keep track of the path and reconstruct the entire JSON obj ...

npm ERROR: Unable to install the package named "<packageName>" because it conflicts with an existing package of the same name

Currently, I am attempting to incorporate the jsonfile package into my project. However, I am encountering a couple of errors: An issue arises when attempting to install a package with the same name as another package within the same directory. (Despite ...

CSS - Absolute positioning appears to be slightly choppy in Microsoft Edge

I have successfully implemented a slip scrolling function to reveal/hide a fixed logo on scroll, but I am facing some issues with Microsoft Edge browser. While testing in various browsers, everything works smoothly except for Microsoft Edge. In this brows ...