Невозможно загрузить путь к файлу для файлов (3D-моделей) с Node.js Server и 3. js - PullRequest
0 голосов
/ 01 августа 2020

У меня проблемы с загрузкой 3D-моделей из папки на моем компьютере с использованием тестового сервера localhost node.js с тремя. js библиотеками.

app. js: (Я запускаю его через командную строку в каталоге проекта, используя: node app.js command)

var app = require('express')();
var http = require('http').createServer(app);
var io = require('socket.io')(http);
var THREE = require('three');

app.get('/', function(req, res) {
    res.sendFile(__dirname + '/index.html');
});
io.on('connection', (socket) => {
  console.log('a user connected');
});

http.listen(3000, () => {
  console.log('listening on *:3000');
});

Соответствующая часть индекса. html:

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>Index.html title</title>

</head>

<body>
    
<script src="/socket.io/socket.io.js"></script> 
<script src="//threejs.org/build/three.js"></script> 
<script src="//threejs.org/examples/js/loaders/AMFLoader.js"></script>
<script src="//threejs.org/examples/js/controls/OrbitControls.js"></script>

<script>
    
    var socket = io();
    
    var camera, scene, renderer;

    init();

    function init() {
        scene = new THREE.Scene();
        scene.add( new THREE.AmbientLight( 0x999999 ) );
        camera = new THREE.PerspectiveCamera( 35, window.innerWidth / window.innerHeight, 1, 500 );
        camera.up.set( 0, 0, 1 );
        camera.position.set( 0, -9, 6 );
        camera.add( new THREE.PointLight( 0xffffff, 0.8 ) );
        scene.add( camera );
        var grid = new THREE.GridHelper( 25, 1.0, 0xffffff, 0x555555 );
        grid.rotateOnAxis( new THREE.Vector3( 1, 0, 0 ), 90 * ( Math.PI/180 ) );
        scene.add( grid );
        renderer = new THREE.WebGLRenderer( { antialias: true } );
        renderer.setClearColor( 0x999999 );
        renderer.setPixelRatio( window.devicePixelRatio );
        renderer.setSize( window.innerWidth, window.innerHeight );
        document.body.appendChild( renderer.domElement );
        
        /* everything up till here works */

        var loader = new THREE.AMFLoader(); 
        loader.load('/models/rook.amf', function ( amfobject ) { //'./models/rook.amf'

            scene.add( amfobject );
            render();

        } );

        /* ^^^ this is the part not working */

        var controls = new THREE.OrbitControls( camera, renderer.domElement );
        controls.addEventListener( 'change', render );
        controls.target.set( 0, 1.2, 2 );
        controls.update();
        window.addEventListener( 'resize', onWindowResize, false );

    }
    function onWindowResize() {
        camera.aspect = window.innerWidth / window.innerHeight;
        camera.updateProjectionMatrix();
        renderer.setSize( window.innerWidth, window.innerHeight );
        render();
    }
    function render() {    
        renderer.render( scene, camera );
    }
</script>
</body>
</html>

Мой каталог проекта:

введите описание изображения здесь

Ошибка:

GET http://localhost:3000/models/rook.amf 404 (Not Found)

Как правильно загружать файлы с помощью Node и 3. js на моем простом тесте сервера?

Ответы [ 3 ]

2 голосов
/ 05 августа 2020

Попробуйте воссоздать эти шаги из кода из вопроса . И у тебя тоже все получится. Возможно, в вашем реальном коде есть что-то еще, чего не хватает в вопросе. Затем вы должны обновить его этой информацией.

  1. Я скопировал ваши app.js и index.html.
  2. Я загрузил rook.amf из https://threejs.org/examples/models/amf/rook.amf и поместил его в /models. Я полагаю, вы сделали то же
  3. , которое я добавил app.use(), как уже правильно предложили другие.
    const express = require('express')
    const app = express()
    const http = require('http').createServer(app)
    // const io = require('socket.io')(http) // unrelated
    // const THREE = require('three') // unrelated
    app.use('/models', express.static('models')) // add this!
    app.get('/', function(req, res) { res.sendFile(__dirname + '/index.html') })
    // io.on('connection', (socket) => console.log('a user connected')) // unrelated
    http.listen(3000, () => console.log('listening on *:3000'))
    
  4. И я смог загрузить rook.amf с AMFLoader. Понятия не имею, как вам удалось получить ошибку THREE.AMFLoader: Error loading AMF - no AMF document found., которую вы упомянули в комментариях.
  5. Но затем я получаю THREE.AMFLoader: jszip missing and file is compressed. Обратите внимание на предупреждение в консоли
    THREE.AMFLoader: As part of the transition to ES6 Modules, the files in 'examples/js' were deprecated in May 2020 (r117) and will be deleted in December 2020 (r124). You can find more information about developing using ES6 Modules in https://threejs.org/docs/#manual/en/introduction/Installation.
    
    Возможно, вам стоит попробовать mimi c это обновлено пример https://threejs.org/examples/webgl_loader_amf.html который я вроде как сделал ...
  6. Я скачал jszip.module.min.js из вышеупомянутого примера. И поместил его тоже в /models, просто для простоты. И добавлен к index.html как
    <script type="module">
      import { JSZip } from "./models/jszip.module.min.js"
      window.JSZip = JSZip
    </script>
    ...
    <!-- I also had to add type="module" to the "main" script
         so it would be executed after window.JSZip = JSZip -->
    <script type="module">
      var socket = io();
      ...
    
    . Но эта часть вам не нужна, если вы будете использовать обновленную версию примера с модулями es6 или загрузите non-es6 версию jszip* 1042. *
  7. Теперь я вижу ладью на экране!
2 голосов
/ 05 августа 2020

Вам необходимо передать содержимое папки models как файлы c stati. Пример:

app.use('/models', express.static('models'))
1 голос
/ 05 августа 2020

Большинство популярных расширений 3D-форматов (.glb, .gltf, .fbx, .dae, .amf, ...) не являются стандартными. Типы MIME , браузеры уделяют особое внимание манипулированию этими файлы, пытаясь защитить пользователя от опасного поведения.

Таким образом, вам нужно будет настроить механизм вашего веб-сервера, чтобы он принимал эти расширения, иначе вы получите различные ошибки HTTP при их загрузке. .amf нет даже в этом списке, поэтому application/octet-stream - значение по умолчанию для всех остальных случаев. Неизвестный тип файла должен использовать этот тип.
Если вы используете сервер IIS из приложения ASP. Net, добавьте строки xml ниже в </system.webServer> узел вашего файла web.config :

<system.webServer>
      ...
      <staticContent>
          <remove fileExtension=".mtl" />
          <mimeMap fileExtension=".mtl" mimeType="model/mtl" />
          <remove fileExtension=".obj" />
          <mimeMap fileExtension=".obj" mimeType="model/obj" />
          <remove fileExtension=".glb" />
          <mimeMap fileExtension=".glb" mimeType="model/gltf-binary" />
          <remove fileExtension=".gltf" />
          <mimeMap fileExtension=".gltf" mimeType="model/gltf+json" />
          <remove fileExtension=".fbx" />
          <mimeMap fileExtension=".fbx" mimeType="application/octet-stream" />
          <remove fileExtension=".amf" />
          <mimeMap fileExtension=".amf" mimeType="application/octet-stream" />
      </staticContent>
</system.webServer>

Если вы используете сервер nginx, добавьте следующие строки в * 1072 Файл * .conf в объекте http:

http {
    include /etc/nginx/mime.types;
    types {
        model/mtl mtl;
        model/obj obj;
        model/gltf+json gltf;
        model/gltf-binary glb;
        application/octet-stream fbx;
        application/octet-stream amf;
    }
    ...
}

Если вы используете сервер Apache, добавьте следующие строки в mime. types file:

model/mtl mtl
model/obj obj
model/gltf+json gltf
model/gltf-binary glb
application/octet-stream fbx
application/octet-stream amf

Для любого другого веб-сервера вы наверняка легко найдете, как установить конфигурацию типов MIME.

EDIT: В случае узла, просмотрите свой файл server.js не включает никаких ограничений для этих типов MIME, большинство популярных сценариев server.js включают ограничения для нестандартных типов MIME

EDIT2: Я ПОЛУЧИЛ как я и подозревал, это было связано с AMF типа MIME. Я опубликовал полное решение на GitHub

Но важные вещи, которые нужно изменить, - это следующие ниже.

Первый , измените app.js чтобы добавить тип MIME.

const express = require('express');
const app = express();
const path = require('path');
const router = express.Router();

router.get('/', function (req, res) {
    res.sendFile(path.join(__dirname + '/index.html'));
    //__dirname : It will resolve to your project folder.
});

app.use('/models', express.static('models')) // add this!
app.use('/express', express.static('express')) // add this!
express.static.mime.define({ 'application/octet-stream': ['amf'] })
//add the router
app.use('/', router);
app.listen(process.env.port || 3000);

console.log('Running at Port 3000');

Второй , из-за недавних изменений в 3. js (23 апреля), использование загрузчика AMF, требует модуля jszip. Нет необходимости загружать его локально, вы можете использовать его по URL-адресу, как и другие файлы js. В моем проекте index. html находится в папке / express, поэтому мой путь к модели amf: ../models/rock.amf

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="utf-8" />
    <title>Index.html title</title>
</head>

<body>

    <script src="https://threejs.org/build/three.min.js"></script>
    <script src="https://threejs.org/examples/js/libs/jszip.min.js"></script>
    <script src="https://threejs.org/examples/js/loaders/AMFLoader.js"></script>
    <script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>

    <script>
        var camera, scene, renderer;

        init()

        function init() {
            scene = new THREE.Scene();
            scene.add(new THREE.AmbientLight(0x999999));
            camera = new THREE.PerspectiveCamera(35, window.innerWidth / window.innerHeight, 1, 500);
            camera.up.set(0, 0, 1);
            camera.position.set(0, -9, 6);
            camera.add(new THREE.PointLight(0xffffff, 0.8));
            scene.add(camera);
            var grid = new THREE.GridHelper(25, 1.0, 0xffffff, 0x555555);
            grid.rotateOnAxis(new THREE.Vector3(1, 0, 0), 90 * (Math.PI / 180));
            scene.add(grid);
            renderer = new THREE.WebGLRenderer({ antialias: true });
            renderer.setClearColor(0x999999);
            renderer.setPixelRatio(window.devicePixelRatio);
            renderer.setSize(window.innerWidth, window.innerHeight);
            document.body.appendChild(renderer.domElement);

            /* NOW IT WORKS!!! */

            var loader = new THREE.AMFLoader();
            loader.load('../models/rook.amf', function (amfobject) { //'./models/rook.amf'

                scene.add(amfobject);
                render();

            });

            /* ^^^ this is the part not working */

            var controls = new THREE.OrbitControls(camera, renderer.domElement);
            controls.addEventListener('change', render);
            controls.target.set(0, 1.2, 2);
            controls.update();
            window.addEventListener('resize', onWindowResize, false);

        }
        function onWindowResize() {
            camera.aspect = window.innerWidth / window.innerHeight;
            camera.updateProjectionMatrix();
            renderer.setSize(window.innerWidth, window.innerHeight);
            render();
        }
        function render() {
            renderer.render(scene, camera);
        }
    </script>
</body>
</html>

Вы получили это ... введите описание изображения здесь

...