KrakenD:使用 Form-Data 通过 POST 请求通过网关上传文件时遇到问题

发布于 2025-01-16 04:50:30 字数 2150 浏览 5 评论 0原文

描述您想要做什么

在我的一个应用程序中,我需要从我的角度网站将文件上传到我的服务器。 基本上,为此,我使用 FormData 对象来附加一些信息,例如文件名等。 为了发送文件本身,我将在 FormData 中附加一个 fs.readStream()。 然后我通过 axios 将其发布到我的服务器端点。

代码示例(使用表单数据的邮递员请求):

var axios = require('axios');
var FormData = require('form-data');
var fs = require('fs');
var data = new FormData();

data.append('avatar', fs.createReadStream('/home/file.mp3'));
data.append('title', 'test');
data.append('description', 'test');
var config = {
  method: 'post',
  url: 'localhost:8080/upload-file',
  headers: { 
    ...data.getHeaders()
  },
  data : data
};

axios(config)
.then(function (response) {
  console.log(JSON.stringify(response.data));
})
.catch(function (error) {
  console.log(error);
});

关于服务器,它是在node.js中开发的,我使用“multer”中间件来检索文件。

端点代码示例:

import {Response, Request} from "express";
public static async UploadFile(req: Request, res: Response): Promise<any> { }

没有 krakend 网关,它可以完美工作,然后我可以检索端点中的文件,以便: req.file 其他发送的信息如“标题”,“描述”都在req.body中

使用krakend,我得到了服务器端除文件之外的所有信息,在请求中,我只找到了req.body而不是req.file

所以我的问题是,为什么 krakend 不将文件数据发送到后端,以及通过 POST 请求 FormData 将文件发送到 krakend 的解决方案是什么?

您的配置文件 krakend.json 的内容:

{
  "version": 3,
  ...
  {
      "endpoint": "/upload",
      "method": "POST",
      "output_encoding": "no-op",
      "backend": [
        {
          "method": "POST",
          "encoding": "no-op", 
          "url_pattern": "/upload-file",
          "host": [
            "http://containername:8080"
          ]
        }
      ]
    }
}

我尝试使用不同的“no-op”注释,但没有任何作用,我的印象是 krakend 无法解释我的文件上传

使用的命令 您是如何启动该软件的?

I use docker-compose:

  krakend:
    container_name: 'Gateway'
    image: devopsfaith/krakend
    volumes:
      - ./KrakenD/dev/:/etc/krakend
    ports:
      - "8080:8080"
      - "1234:1234"
      - "8090:8090"
    links:
      - some containers
      - ...
    restart: always
    network_mode: bridge

日志 我没有特定的日志,只有我的后端返回 400 代码,因为它找不到请求中的文件信息。

Describe what are you trying to do

In one of my applications, I need to upload a file to my server from my angular website.
Basically, to do this I use the FormData object to which append several informations, like the file name, and others.
To send the file itself I will append to the FormData an fs.readStream().
Then I post this via axios to my server endpoint.

Exemple of code (postman request using form-data):

var axios = require('axios');
var FormData = require('form-data');
var fs = require('fs');
var data = new FormData();

data.append('avatar', fs.createReadStream('/home/file.mp3'));
data.append('title', 'test');
data.append('description', 'test');
var config = {
  method: 'post',
  url: 'localhost:8080/upload-file',
  headers: { 
    ...data.getHeaders()
  },
  data : data
};

axios(config)
.then(function (response) {
  console.log(JSON.stringify(response.data));
})
.catch(function (error) {
  console.log(error);
});

Concerning the server, it is developed in node.js and I use the "multer" middleware to retrieve the file.

Exemple of an endpoint code :

import {Response, Request} from "express";
public static async UploadFile(req: Request, res: Response): Promise<any> { }

Without krakend gateway, it's works perfectly and I can then retrieve the file in my endpoint so that: req.file
The others informations sent like "title", "description" are in req.body

Using krakend, I get all the information on the server side except the file, in the request, I only find the req.body and not the req.file

So my question is, how come krakend is not sending the file data to the backend and what would be the solution in order to send file via POST request a FormData to krakend ?

Your configuration file
The content of your krakend.json:

{
  "version": 3,
  ...
  {
      "endpoint": "/upload",
      "method": "POST",
      "output_encoding": "no-op",
      "backend": [
        {
          "method": "POST",
          "encoding": "no-op", 
          "url_pattern": "/upload-file",
          "host": [
            "http://containername:8080"
          ]
        }
      ]
    }
}

I tried to use the different "no-op" annotations but nothing works, I have the impression that krakend does not interpret my file upload

Commands used
How did you start the software?

I use docker-compose:

  krakend:
    container_name: 'Gateway'
    image: devopsfaith/krakend
    volumes:
      - ./KrakenD/dev/:/etc/krakend
    ports:
      - "8080:8080"
      - "1234:1234"
      - "8090:8090"
    links:
      - some containers
      - ...
    restart: always
    network_mode: bridge

Logs
I don't have a specific log, only my backend which returns a 400 code as it can't find the file information in the request.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

妞丶爷亲个 2025-01-23 04:50:30

对于那些正在经历同样问题的人。请注意,邮递员是造成我问题的原因,KrakenD 确实支持将正文作为多部分/表单数据发送,因此不要忘记根据需要让标头通过。

问题是,当通过邮递员时,我无法解释,但文件发送到 krakenD 的情况很糟糕。使用 Insomnia 或简单的 Curl 进行测试。

for those who are going through the same problem. Please note that postman was the cause of the problem for me, KrakenD does support sending bodies as multipart/form-data, so don't forget to let the headers through as needed.

The problem is that when passing through postman, I can't explain but the file is badly sent to krakenD. Use Insomnia, or a simple Curl to do your tests.

梦里兽 2025-01-23 04:50:30

也许您必须在输入标题中包含“Content-Type”。

"input_headers": [
        "Authorization",
        "Content-Type"
],

在这里您可以找到有关它的更多信息。

Maybe you have to include "Content-Type" at input-headers.

"input_headers": [
        "Authorization",
        "Content-Type"
],

Here you can find more info about it.

萧瑟寒风 2025-01-23 04:50:30

我遇到了同样的问题,我解决了它,包括标题中的“Content-Type”。我在端点中使用一些模板来进行一些额外的配置。

{
  "output_encoding": "no-op",
  "method": "GET",
  "endpoint": "/my-endpoint/",
  "backend": [
    {
      "url_pattern": "/my-endpoint/",
      "host": ["{{ $host }}"]
    }
  ],
  {{ template "MyConfig" $my_roles}}
}

{{ define "AuthValidator" }}
  "extra_config" : {
      "auth/validator": {
          {{ template "DefaultAuthConfig" . }}
      }
    }
{{ end }}


{{ define "MyConfig" }}
  "input_headers": [{{ include "auth_headers.inc" }}],
  {{ template "AuthValidator" }}
{{ end }}

我在端点中仅包含“AuthValidator”,然后手动包含我的 input_headers,如下所示:

{
  "output_encoding": "no-op",
  "method": "POST",
  "endpoint": "/my-endpoint",
  "backend": [
    {
      "encoding": "no-op",
      "url_pattern": "/my-endpoint",
      "host": ["{{ $host }}"]
    }
  ],
  {{ template "MyConfig" $my_roles }},
  "input_headers": [{{ include "auth_headers.inc" }}, "Content-Type"]
}

当您使用模板时,模板会覆盖同一级别中的某些参数,因此我必须将 MyConfig 分成 2 个级别以允许自定义配置来自模板。

I had the same problem, I solved it incluind "Content-Type" in headers. I'm using some template in my endpoints to some extra configs.

{
  "output_encoding": "no-op",
  "method": "GET",
  "endpoint": "/my-endpoint/",
  "backend": [
    {
      "url_pattern": "/my-endpoint/",
      "host": ["{{ $host }}"]
    }
  ],
  {{ template "MyConfig" $my_roles}}
}

{{ define "AuthValidator" }}
  "extra_config" : {
      "auth/validator": {
          {{ template "DefaultAuthConfig" . }}
      }
    }
{{ end }}


{{ define "MyConfig" }}
  "input_headers": [{{ include "auth_headers.inc" }}],
  {{ template "AuthValidator" }}
{{ end }}

I include only "AuthValidator" in my endpoint and then include my input_headers manually, like this:

{
  "output_encoding": "no-op",
  "method": "POST",
  "endpoint": "/my-endpoint",
  "backend": [
    {
      "encoding": "no-op",
      "url_pattern": "/my-endpoint",
      "host": ["{{ $host }}"]
    }
  ],
  {{ template "MyConfig" $my_roles }},
  "input_headers": [{{ include "auth_headers.inc" }}, "Content-Type"]
}

When you use a template, the template overwrite some param in the same level, so I've to split MyConfig in 2 levels to allow a custom config from a template.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文