【问题标题】:Keep getting 404 Error for static JSON with axios (vue cli)使用 axios (vue cli) 不断收到静态 JSON 的 404 错误
【发布时间】:2020-03-15 13:41:05
【问题描述】:

我开始了一个简单的 Vue 项目,并遇到了静态数据的第一个问题。 我有一个 json 文件 tours.json,它通过 axios GET 请求不断收到 404 错误。

    <script>
    import axios from 'axios';
    const tours = 'http://localhost:8080/server/tours.json';
    export default {
        name: "TourInformations",
        data() {
            return {
                tourInformations: ''
            };
        },
        methods: {},
        created() {
            axios.get(tours).then(res => {
                console.log(res);
            }).catch(err => console.log(err))

        }  
    };
    </script>

我尝试的第一件事是更改我的 json 文件的路径。没有帮助。 我尝试使用相对路径,使用localhost:8080http:// 分别使用https://

控制台一直在说:

GET http://localhost:8080/server/tours.json 404 (Not Found)

Error: Request failed with status code 404
    at createError (createError.js?2d83:16)
    at settle (settle.js?467f:17)
    at XMLHttpRequest.handleLoad (xhr.js?b50d:59)

感谢您的每一个帮助!

编辑:奇怪的是,当我使用 jsonplaceholder 之类的外部 API 或其他具有相同代码的 API 时,我得到了响应。为什么是这样? 将我的地址更改为 https:// 会显示 CORS 错误。我不认为我以更好的方式与 CORS 合作。我糊涂了。特别是作为初学者,我无法理解为什么本地 JSON 文件的简单路径不起作用,但安全外部 API 的路径却可以。

Edit2:将我的/server/tours.json 放入public 文件夹现在可以。数据显示在console 中。 现在这是我的json 文件的存储位置:'http://localhost:8080/public/server/tours.json。 在这里一切都好。

但是当我将我的json 文件移动到其他每个文件夹并相应地更改我的路线时。无论我如何尝试将我的路线调整到我的json 文件的新位置,它都会一直显示 404 错误。 例如: 如果我将/server/tours.json 移动到我的src 目录中,请将我的axios 路径 http://localhost:8080/server/tours.json 更改为 http://localhost:8080/src/server/tours.json 它显示404 (GET http://localhost:8080/src/server/tours.json 404 (Not Found))。我的文件的路径应该像这样正确。 一个 404 也出现了一个相对路径,如../server/tours.json。 (我上面的 axios 代码放置在我正在更改路径的组件中,具体取决于我的 json 的位置。

这是我的(简化的)文件结构:

    root
    ├── public
    ├────── favicon.ico
    ├────── index.html
    ├────── server
    ├──────────tours.json
    ├── src
    ├────── assets
    ├────── components
    ├───────── Tours.vue ###My axios code in here
    ├──────────── ...
    ├────── App.vue
    ├────── main.js
    ...

具有上述文件结构的路由http://localhost:8080/public/server/tours.json 有效。好的。

这是显示404 Error 的文件结构和路径。 http://localhost:8080/src/server/tours.json

    root
    ├── public
    ├────── favicon.ico
    ├────── index.html
    ├── src
    ├───────server
    ├──────────tours.json
    ├────── assets
    ├────── components
    ├───────── Tours.vue ###My axios code in here
    ├──────────── ...
    ├────── App.vue
    ├────── main.js
    ...

所以public 中的json 有效,外部API 有效。 axios sn -p 是正确的。是关于绳索的吧?我尝试了(感觉像)所有可能导致问题的路线。我很困惑。

我想念什么?这个话题应该短得多。所以,我在这里想念一些东西。否则我无法解释为什么像正确的文件路径这样简单的事情似乎如此令人困惑。

显然不是路线错了。即使我将json 移动到root 并将路径更改为http://localhost:8080/tours.json,它也会显示404

【问题讨论】:

  • localhost:8080 是您的 Vue 开发服务器的地址还是其他服务器?相对于您的 Vue 文件,您将文件 tours.json 放在文件系统的哪个位置?如果您直接在 Web 浏览器中打开 URL,直接在地址栏中输入 URL,会发生什么情况?直到您可以正常工作,您才能编写合适的代码从 UI 中检索它。从表面上看,问题似乎是文件系统上文件的位置与您用来访问它的 URL 不匹配。
  • 这是我的Vue开发服务器的地址。我的 tours.json 在单独的 server 文件夹中的 src 之外。如果我在浏览器中输入 URL,它会像往常一样将我带到我的 Vue 应用程序。

标签: json vue.js axios command-line-interface http-status-code-404


【解决方案1】:

我认为这里的主要问题是您拥有 .json 文件,但您需要一个服务器来实际发送回对您的 GET http 请求的响应,在此响应中您将拥有 json 数据。

综上,axios创建了一个http请求,本例是GET请求,而你需要另外的软件来响应这个http协议,这个响应会包含json数据,headers等。

我建议为此研究类似 express 框架的东西。

【讨论】:

  • 我不确定你的意思。你能给我一个例子吗?据我正确理解,我的 axios 代码至少应该在我的控制台中使用正确的 json 数据返回响应。但该文件未显示。使用相同的代码 sn-p 显示外部 API。
【解决方案2】:

我认为问题只是您将文件放在文件系统上的错误位置。

假设您使用的是 Vue CLI 并且想要 URL:

http://localhost:8080/server/tours.json

那么你应该把文件放在路径:

project-root/public/server/tours.json

作为参考,index.html 通常位于路径中:

project-root/public/index.html

官方文档:

https://cli.vuejs.org/guide/html-and-static-assets.html#static-assets-handling

还有其他方法可以使用服务器的自定义配置来实现类似的效果,但将静态资产放入public 文件夹应该可以直接使用。

更新:

根据您的 cmets 和更新后的问题,我将尝试进一步解释。

首先,这里完全忽略 axios 部分。正如您在问题中所建议的那样,这不是问题。您可以通过直接在浏览器地址栏中输入这些 URL 来复制完全相同的行为,您将获得与使用 axios 相同的 404。

这里的根本问题似乎是您认为项目根文件夹中的文件结构与“路由”或 URL 路径之间存在直接对应关系。不是这种情况。它们是两个不同的东西。

让我们考虑一下当您向网络服务器发出请求时会发生什么。不一定是 Vue 开发服务器,任何 Web 服务器。

当您向网络服务器发出请求时,该服务器完全可以自行决定返回什么内容。因此,对http://localhost:8080/server/tours.json 的请求涉及通过localhost:8080 联系服务器并要求它提供server/tours.json

从表面上看,这似乎是从文件夹 server 中请求 文件 tours.json。但是,情况不一定如此。由服务器决定server/tours.json 的含义和响应应该是什么。响应不仅不必针对文件的内容,甚至不必是静态的。服务器可以即时生成响应,可能基于数据库查询的结果。

了解这一点非常重要。发送http://localhost:8080/server/tours.json 的请求并不一定意味着'给我来自文件夹server'的文件tours.json'。完全由服务器自行决定返回什么。

现在,Web 服务器必须处理静态资产是很常见的。存储此类资产的最简单方法是作为文件。与配置 URL 路径和文件系统路径之间的单独映射相比,通常更容易将文件组织在文件夹结构中,以便方便地映射到 URL 路径。通常,Web 服务器将被配置为将特定文件夹视为静态资产的“根”,然后将使用匹配的 URL 路径提供该根中的所有文件夹/文件。

一般来说,具体的配置机制取决于您使用的网络服务器。当然,我们对 Vue 开发服务器特别感兴趣,所以让我们回过头来考虑那个特定的服务器。

Vue 开发服务器在幕后发生了很多事情。它不仅仅是从文件系统中提供文件。

src 文件夹的内容需要构建。它们不会按原样提供给浏览器。服务器不会将它们视为静态资产。如果您尝试访问http://localhost:8080/src/App.vue,您会发现收到 404 响应。这是意料之中的事。

相反,服务器将遍历src 文件夹的内容并生成它需要的“文件”。例如,它将分离所有.js.vue 文件并使用它们创建一个包含所有内容的大app.js。如果您查看浏览器开发人员工具的“网络”选项卡,您应该会看到正在加载的“文件”app.js。但是这个“文件”实际上并不存在,它是根据src文件夹中的文件内容动态生成的。

然而,一个 Vue 项目需要一些静态资源是很常见的。默认 CLI 项目将具有 index.htmlfavicon.ico。这些不需要动态生成,因此只需将它们作为文件存储在文件系统上就很方便。 Vue 服务器有一个特殊的文件夹,称为public,用于保存这些文件。如前所述,该文件夹中的任何文件夹/文件都将直接映射到等效的 URL 路径(问题称为 routes)。文件夹public 被视为这些映射的根文件夹。因此,位于文件系统 project-root/public/server/tours.json 的文件将映射到 URL 路径 server/tours.json,完整的 http://localhost:8080/server/tours.json。 “路由”是相对于public 文件夹,而不是相对于项目的根文件夹。

虽然这涵盖了最重要的细节,但为了完整起见,我还要注意一些其他事项。

首先,严格来说public 文件夹的内容并非都是静态的。对于文件index.html,有一些Webpack 的魔法继续在页面中注入各种东西。这被描述为here,但在了解如何提供一个简单的.json 文件时,它不值得细说。

其次,也可以在src 文件夹中包含静态资产,但仅限于特定情况。例如,默认的 Vue CLI 项目在 src/assets/logo.png 创建一个文件。然而,这里还有更多的 Webpack 魔法。一旦构建完成,它将有一个类似http://localhost:8080/img/logo.82b9c7a5.png 的 URL。请注意,这与文件系统上的原始路径有很大不同。 Webpack 将遍历您的 .js.vue 文件,并尝试更新任何访问 src/assets/logo.png 的相对路径,以将它们指向生成的路径。我不打算详细说明它在这里是如何工作的,因为我认为它与原始问题无关。请注意,它何时起作用是有限制的,它实际上并不神奇。

访问src 文件夹中的.json 文件有一些等效的方法,但它根本不会生成“路由”。如果您将.json 文件放在src 文件夹中的某个位置,那么您可以使用import 导入它,就像使用.js.vue 文件一样:

import tours from '../server/tours.json'

重要的是要明白这不是向服务器发出单独的 AJAX 请求来加载文件。相反,这是告诉 Webpack 在构建期间将 tours.json 的内容捆绑到 app.js 中。如果您以这种方式包含tours.json,则不会为它创建“路线”。

我现在将讨论问题中的一些具体评论,以试图澄清误解似乎潜伏在哪里。

将我的/server/tours.json 放入public 文件夹现在可以。数据显示在console 中。现在这是存储我的 json 文件的位置:http://localhost:8080/public/server/tours.json。在这里一切都好。

如果您将文件放在文件系统上的public/server/tours.json,那么它将被映射到http://localhost:8080/server/tours.json 的URL。 public 将被删除,因为它在提供静态文件时被视为根。

在上面的引用中,您声称该文件存储在http://localhost:8080/public/server/tours.json。我不相信这是正确的。正如您之前在 cmets 中所述,URL 路径将不包含 /public 部分。

您应该能够通过直接在浏览器的地址栏中输入 URL 路径来测试它们。

如果您需要澄清 axios 调用的 URL,请查看浏览器开发人员工具的“网络”选项卡。这将显示它请求的完整 URL。

但是当我将我的 json 文件移动到其他所有文件夹并相应地更改我的路线时。不管我如何尝试使我的路由适应我的json 文件的新位置,它一直显示 404 错误。

Vue 服务器不会为所有文件创建路由。它只为public 文件夹中的文件创建路由。因此,如果您将文件放在public 文件夹之外的某个位置,则不会有相应的路线。再多的调整 URL 也无济于事,路由不存在。

例如:如果我将/server/tours.json 移动到我的src 目录中,请将我的axios 路径 http://localhost:8080/server/tours.json to http://localhost:8080/src/server/tours.json 更改为http://localhost:8080/src/server/tours.json 它显示404 (GET http://localhost:8080/src/server/tours.json 404 (Not Found)) .我的文件的路径应该是这样正确的。

别怕。

将它放在src 文件夹中不会对可用路由产生任何影响。只有将它放在public 文件夹中才会导致创建路由。

您的src 文件夹中可能还有其他几个文件。这些文件都不会直接映射到路由上。如果您尝试访问 http://localhost:8080/src/components/Tours.vue,您将得到 404。相反,这些文件被捆绑到 Webpack 构建中。

如果您的文件系统上有文件src/server/tours.json,那么您可以在.js.vue 文件中使用import 访问其内容。但是,这一切都由构建过程处理,与创建可通过 URL 访问的路由无关。这与通过 axios 加载文件的过程非常不同。

显然不是路线错了。即使我将json 移动到root 并将路径更改为http://localhost:8080/tours.json,它也会显示404。

如果您想使用 URL http://localhost:8080/tours.json 访问文件,那么将其放入文件系统的正确位置是:

project-root/public/tours.json

回想一下,提供静态文件的根目录是 public 文件夹。它不是项目的根文件夹。如果您将文件放在public 文件夹之外,那么服务器通常会忽略它们。

【讨论】:

  • 它适用于public,谢谢!但是为什么路由忽略了public?我需要弄清楚,当我添加像http://localhost:8080/public/server/tours.json 这样的路线时,它 工作,但删除public 并使其http://localhost:8080/server/tours.json 工作正常。我在文档中找不到解释。但是,如果我将json 文件放在另一个文件夹中,它仍然显示404。即使我检查了几次我的路线是否错误。需要找出来。再次感谢您的帮助!
  • @DamirLucic 您似乎错误地期望服务器只会提供所有文件,无论您将它们放在哪里。这不是它的工作原理。 public 文件夹很特殊。该文件夹中的文件将作为“静态资产”提供,使用与public 文件夹 文件路径等效的 URL。如果您想提供一个静态文件,请将其放在public 文件夹中,就这么简单。如果您只是将它放在其他随机文件夹中,它将被忽略。
  • 我不希望服务器会为所有文件提供服务,无论它们放在哪里。我编辑了我的第一篇文章并试图准确解释我为什么感到困惑。
  • @DamirLucic 我已根据您更新的问题为我的答案添加了更新。然而,虽然我已经深入了很多细节,但我的答案基本保持不变。
  • 感谢非常详细的解释。上周看的,信息量挺多的,今天又看了一遍,发现我对代码背后的整个过程有很多误解。我检查了你提到的事情,确实,你是对的。在你回答之前,我接受了这样一个事实,即我不能像我想要的那样传递一个 URL,并继续“以正常方式”导入文件(就像你提到的那样)
【解决方案3】:

我在 .json 文件中有针对此类问题的替代解决方案

第一件事是

import projects from '../../static/projects.json' // 在你的组件中导入这个文件

在数据中声明一个空数组

data() {
    return {
        items: []
    }
},

然后创建一个生命周期方法,如 created 或 Mounted 等。

created () {
        let projectData = projects.projects
        return this.items.push(...projectData)
    }

不使用 fetch 或 axios 就可以正常工作。

【讨论】:

    猜你喜欢
    • 2019-12-06
    • 1970-01-01
    • 2018-07-28
    • 2023-03-11
    • 2022-11-26
    • 1970-01-01
    • 1970-01-01
    • 2018-05-24
    • 1970-01-01
    相关资源
    最近更新 更多