刷新页面显示文件未找到错误如何解决使用[angular js + NodeJS / ExpressJS]

时间:2017-01-02 06:13:24

标签: javascript angularjs node.js express

注意:我尝试了所有问题&回答相关这个话题。像这样,我尝试了相关的问题并试图解决它,但没有成功。

我正在构建angularJS web-app。它纯粹基于 AngularJS / HTML 5和 NodeJS / ExpressJS ,数据库端使用 mongo DB ,则会出现此问题。

我想 '#'在网址中移除我刷新页面然后显示当前页面。但是现在显示&#34;未找到404&# 34;。我使用$locationProvider.html5Mode(true);<base href="/" />,但我没有成功。

  

我知道删除网址解决方案中的$locationProvider.html5Mode(true);和   <base href="/" />但我使用 NodeJS / ExpressJS 然后我无法使用。

我的网址

http://localhost:3000/Tutorial/Routing/StateProvider/index.html#/Setting/StudenList

我想要网址

http://localhost:3000/Tutorial/Routing/StateProvider/index.html/Setting/StudenList

备注:

没有此解决方案$locationProvider.html5Mode(true);和  <base href="/" />但我使用 NodeJS / ExpressJS 然后我想删除#并刷新页面问题解决

代码

Folder Structure directive 。我的代码非常长,然后我管理片段(在html&amp; js 中)。 没有运行代码段,因为我插入了所有代码只是为了解我的代码是什么错误。

sample2(refreshissue) [Project Name]
-- Public
    -- Tutorial
        --Directive
            -index.html
        --Routing
           --StateProvider
                -Account.html
                -index.html
                -Setting.html
                -StudentListing.html
                -studentDetails.html
                -StateProviderController.js
        --Validation
          -index.html
 -index.html

&#13;
&#13;
--  StateProviderController.js
---------------------------------------------------------------------------------
var myapp= angular.module('myapp2',["ui.router"]);
myapp.config(function($stateProvider,$urlRouterProvider,$locationProvider,$urlMatcherFactoryProvider){
    $urlMatcherFactoryProvider.strictMode(false);
    $stateProvider
.state('TutorialHome', {
            url:'/index',
            templateUrl:'/index.html'
        })
        .state('Profile',{
            url:'/Profile',
            templateUrl:'Profile.html'
        })
        .state('Account',{
            url:'/Account',
            templateUrl:'Account.html'
        })
        .state('Setting',{
            url:'/Setting',
            templateUrl:'Setting.html'
        })
        .state('Setting.StudenListing', {
            url:'/StudenList',
            views: {
                'StudenListing': {
                    templateUrl: 'StudenListing.html',
                    controller:'StudentListingData'
                }
            }
        })
        .state('Setting.StudenListing.StudentList',{
            url:'/StudenList/:StudentID',
            /* templateUrl: 'StudentDetails.html',
            controller:'StudentDetails'*/
            views:{
               'StudentDetails': {
                   templateUrl: 'StudentDetails.html',
                   controller:'StudentDetails'
              }
            }
        })
    ;

   // $urlRouterProvider.otherwise('/index');
 //$locationProvider.html5Mode(true);

});
myapp.controller('StateProviderCtrl',function($scope){
    $scope.message ="Welcome To State Provider Page";
    $scope.Home = function()
    {
        window.open('/',"_self");
    }
});

myapp.controller('StudentListingData',function($scope,$http){
    console.log('test');
$http.get('/StudenRecordData').success(function(response){
   // console.log(response);
    $scope.StudentRecorddata =response;
})
});

myapp.controller('StudentDetails',function($scope,$http,$stateParams){
    $scope.StudentID = $stateParams.StudentID;
    //console.log( $scope.StudentID);

    $http.get('/StuentRecordSearch/'+ $stateParams.StudentID).success(function(response){
        //console.log(response);
        $scope.StuentDetails =response[0];
    })

});
==================================================================================================================================================================
----  app.js
---------------------------------------------------------------------------------
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var url =require('url');

var index = require('./routes/index');

var app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');


//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

app.use('/', index);
/*var basepathArray = ['/Tutorial/Routing/StateProvider/','/Tutorial/Validation/','/Tutorial/Directive/'];
app.get('/!*',function(req,res){
  var basePath ="";
  for(var i=0;i<=basepathArray.length-1;i++)
  {
    if(req.originalUrl.search(basepathArray[i]) != -1){
      basePath =basepathArray[i];
      break;
    }
  }
  if(basePath!="")
  {
    res.sendFile(path.resolve('public'+basePath+'index.html'));
  }
  else {
    res.sendFile(path.resolve('public/index.html'));
  }



});*/

// catch 404 and forward to error handler
app.use(function(req, res, next) {
  var err = new Error('Not Found');
  err.status = 404;
  next(err);
});

// error handler
app.use(function(err, req, res, next) {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};

  // render the error page
  res.status(err.status || 500);
  res.render('error');
});



module.exports = app;
&#13;
=================================================================================
 --  Account.html
---------------------------------------------------------------------------------
<h1>Account  page</h1>

=================================================================================
--  index.html
---------------------------------------------------------------------------------
<!DOCTYPE html>
<html ng-app="myapp2">
<title>Index | Angular Js</title>
<base href="/Tutorial/Routing/StateProvider/" />
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet">

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<!--<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular-route.js"></script>-->
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.3.2/angular-ui-router.js"></script>
<script src="StateProviderController.js"></script>

<body ng-controller="StateProviderCtrl">
<nav class="navbar navbar-default row">
    <div class="container-fluid">
        <div class="navbar-header">
            <a class="navbar-brand" ui-sref="TutorialHome"> State Routing</a>
        </div>
            <ul class="nav navbar-nav">
                <li><a ui-sref="Profile">Profile</a></li><!--State Transition on click-->
                <li><a ui-sref="Account">Account</a></li><!--State Transition on click-->
                <li><a ui-sref="Setting">Setting</a></li><!--State Transition on click-->
                <li style="float: right;" ><a ng-click="Home()"> Home</a></li><!--State Transition on click-->
            </ul>

    </div>
</nav>


<div class="container" ng-controller="StateProviderCtrl">
    <!-- we use ui-view instead of ng-view -->
    <!--{{message}}<br>-->
    <ui-view></ui-view>

</div>


</body>
</html>
=================================================================================
--  Profile.html
--------------------------------------------------------------------------------
<h1>Profile  page</h1>

=================================================================================
--  Setting.html
---------------------------------------------------------------------------------
<div>
    <h1>Setting page</h1>
    <strong>This page shows Nested states & views. Click on below links to see Nested states in action.</strong><br>
    <ul>
        <li><a ui-sref="Setting.StudenListing">Show Listing</a></li>
    </ul>
    <div class="container">

        <div class="row">
            <div class="col-sm-12" style="background-color:beige;display: inline-block">
                <div ui-view="StudenListing"></div>
            </div>
        </div>
    </div>

</div>
  <!--  <div ui-view="Descriptions"></div><br>
    <div ui-view="Price"></div>-->
=================================================================================
--  StudentListing.html
---------------------------------------------------------------------------------
    <!--<ui-view></ui-view>-->


    <div class="row">
        <div class="col-sm-6" style="background-color:beige;">

            <h2>Student Listing</h2>
            <p>All Talented Student List</p>
            <table class="table" >
                <thead>
                <tr>
                    <th>Name</th>
                    <th>Eduction</th>
                    <th>Email ID</th>
                    <th>Details <!--<div ui-view="StudentDetails"></div>--></th>
                </tr>
                </thead>
                <tbody>
                <tr ng-repeat="data in StudentRecorddata">
                    <td>{{data.Name}}</td>
                    <td>{{data.Eduction}}</td>
                    <td>{{data.Email}} </td>
                    <td><button type="button" class="btn btn-info" ui-sref="Setting.StudenListing.StudentList({StudentID:$index})">View Details</button> </td>
                </tr>

                </tbody>
            </table>
        </div>
        <div class="col-sm-6" style="background-color:beige;">
           <!-- <div ui-view="StudenListing"></div>-->
            <div ui-view="StudentDetails"></div>
        </div>
    </div>
=================================================================================
-- studentDetails.html
------------------------------------------------------------------------------<div>
    <h2>Student Details </h2>
    <br>
    <form class="form-horizontal">
        <div class="form-group">
            <label class="control-label col-sm-2" for="email">Stuent Id:</label>
            <div class="col-sm-10">
                <p class="form-control-static">{{StudentID}}</p>
            </div>
        </div>
        <div class="form-group">
           <label class="control-label col-sm-2" for="email">Name:</label>
            <div class="col-sm-10">
                <p class="form-control-static">{{StuentDetails.Name}}</p>
            </div>
        </div>
        <div class="form-group">
            <label class="control-label col-sm-2" for="pwd">Age:</label>
            <div class="col-sm-10">
                <p class="form-control-static">{{StuentDetails.Age}}</p>
            </div>
        </div>
        <div class="form-group">
            <label class="control-label col-sm-2" for="email">Eduction:</label>
            <div class="col-sm-10">
                <p class="form-control-static">{{StuentDetails.Eduction}}</p>
            </div>
        </div>
        <div class="form-group">
            <label class="control-label col-sm-2" for="pwd">Email:</label>
            <div class="col-sm-10">
                <p class="form-control-static">{{StuentDetails.Email}}</p>
            </div>
        </div>
        <div class="form-group">
            <label class="control-label col-sm-2" for="email">MobileNumber:</label>
            <div class="col-sm-10">
                <p class="form-control-static">{{StuentDetails.MobileNumber}}</p>
            </div>
        </div>
        <div class="form-group">
            <label class="control-label col-sm-2" for="pwd">Gender:</label>
            <div class="col-sm-10">
                <p class="form-control-static">{{StuentDetails.Gender}}</p>
            </div>
        </div>

    </form>
</div>
&#13;
&#13;
&#13;

4 个答案:

答案 0 :(得分:10)

  

这是因为接收请求的Web服务器会查找与服务器上的完整URL匹配的资源,这是不存在的,因为URL的角度部分指的是角度应用程序中的路径并且需要在客户端浏览器中处理

解决此问题的方法是将所有虚拟URL重写为主角度index.html文件

  

AngularJS + NodeJS / ExpressJS - 在html5mode中页面刷新后阻止404错误的路由

var express = require('express');
var path = require('path');
var router = express.Router();

// serve angular front end files from root path
router.use('/', express.static('app', { redirect: false }));

// rewrite virtual urls to angular app to enable refreshing of internal pages
router.get('*', function (req, res, next) {
    res.sendFile(path.resolve('app/index.html'));
});

module.exports = router;
  

AngularJS + IIS - URL重写规则,以防止在html5mode页面刷新后出现404错误(对于apache click here

<rewrite>
  <rules>
    <rule name="AngularJS" stopProcessing="true">
      <match url=".*" />
      <conditions logicalGrouping="MatchAll">
        <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
        <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
      </conditions>
      <action type="Rewrite" url="/" />
    </rule>
  </rules>
</rewrite>

Referred from

解决此问题的其他方法

https://stackoverflow.com/a/34817349/2218635

答案 1 :(得分:5)

这就是我的应用程序。

来自API docs的HTML5模式

  

如果启用(HTML5模式)且requireBase为true,则为基数   标签不存在,$ location时会抛出错误   注入。

因此,您需要base标记。我尝试过没有基本标记而且requireBase是假的,但它似乎仍然给我带来了错误。

<强>的index.html

<head>
    <base href="/">
</head>

<强> app.route.js [Angular.js]

app.config(function($stateProvider, $urlRouterProvider, $locationProvider) {

    // This removes '#' and makes URL pretty
    $locationProvider.html5Mode({
        enabled: true,
        requireBase: true
    });

    // Default path if nothing is matched. State would become 'landing'
    $urlRouterProvider.otherwise('/');

    $stateProvider
        .state('landing', {
            url: '/',
            templateUrl: "/dashboard/landing/templates/index.html",
            controller: 'LandingController'
        }).state('about', {
            url: '/about',
            templateUrl: "/dashboard/about/templates/index.html",
            controller: 'AboutController'
        });

});

将自己从'landing'重定向到'about'状态并且路由更改为/about后,只会在浏览器上更改URL,并且服务器不知道这一点。因此,当您刷新时,服务器不知道/about路径的含义。因此,您需要将/about路径(或属于角度路径的任何路径)重定向到index.html,然后将角度重定向到/about自动返回。

<强> app.js [Express.js]

//  dashboard route should deliver templates instead of loading angular JS app so this should come before the next one
app.use('/dashboard', express.static(__dirname + '/public/dashboard'));

// put all the API methods here and separate from the redirection to `index.html`
app.use('/api', routes.apiRoutes); 

// all the paths that do not start with `/dashboard` or `/api` is/should be angular route and thus, redirect back to `index.html`
app.get('*', function (req, res) {
    res.sendFile(__dirname + '/public/index.html');
});

旁注

在另一个应用程序中,我已经看到刷新浏览器在路径末尾附加一个尾部斜杠(/)的问题,并且在重定向之后,Angular应用程序无法识别来自url /about vs /about/所以它会将我重定向回目标网页。

我通过在 app.route.js

中添加此内容来解决此问题
$urlMatcherFactoryProvider.strictMode(false);

我希望这会有所帮助

答案 2 :(得分:0)

您必须更改application-configuration.js文件,如下所示:

请找到这部分:“indexController”

var indexController = function ($scope, $rootScope, $http, $location, blockUI) {
            var baseUrl="/Tutorial"; //here it will be your site name
}

只需在您的网址链接中添加此baseUrl。

答案 3 :(得分:0)

嗯......这个问题是每个人在使用angular.js和angular开始时可能会遇到的问题。

第一期是&#39;#&#39;在网址中,像所有人建议只是这样做

$locationProvider.html5Mode(true);

现在刷新问题将会发生,预计......再次发生。

为什么会这样?

请求被发送到node.js服务器,没有任何地方可以阻止它。

如何解决?

确保将相应的尾随请求映射到主角度视图。如果整个程序只有一个ng-app,那么只需重定向到主视图即可。

在node.js服务器上添加类似的内容

app.get('/', function(req, res) {
  res.sendFile(__dirname + '/index.html');
});

app.get('/*', function(req, res) {
  res.sendFile(__dirname + '/index.html');
});

这里index.html是我的主视图,它链接到主控制器文件,其中存在路由代码。如果我尝试加载/about,它将转到控制器,然后控制器将加载特定视图。

这是解决此问题的简便方法。