如何使用 axios 上传图像到 fastify + graphql 后端? [英] How to upload images to fastify + graphql backend with axios?

查看:37
本文介绍了如何使用 axios 上传图像到 fastify + graphql 后端?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当通过 axios 发送图像时,我发现我必须使用 formdata.我在这里添加了我的图像,但是在发送表单数据时,我的整个后端都冻结了,只是说待定".

我一直在关注

我不完全理解 formdata 将如何到达我的解析器端点,因此我在后端返回后做错了什么:

<块引用>

(节点:748)未处理的PromiseRejectionWarning:[对象数组](节点:748)UnhandledPromiseRejectionWarning:未处理的承诺拒绝.这个错误源于抛出异步函数内部没有 catch 块,或者通过拒绝未处理的承诺用 .catch().(拒绝id:1)(节点:748)[DEP0018]弃用警告:不推荐使用未处理的承诺拒绝.在未来,未处理的承诺拒绝将终止带有非零退出代码的 Node.js 进程.

我意识到这很多,但我在我的 vits 结束时,一整天都在这样做.任何帮助深表感谢.

由于我的后端受到质疑,我想我只会表明,当发送数据而不像上面那样附加 Formdata 时,我就可以正常工作了:

 const submitForm: SubmitForm = (obj: SendObject) =>{调用AxiosFn({方法,url: 'http://localhost:4000/api',数据:obj.data,},qlType.toString());};

obj.data 是:

{query: "mutation ($firstName: String!, $email: String!, $l... Age: $age, JobTitle: $jobTitle, File: $file})↵}↵, 变量:{…}}query: "mutation ($firstName: String!, $email: String!, $lastName: String!, $age: DateTime!, $jobTitle: String!, $file: Upload) {↵ register(input: {FirstName: $firstName, LastName: $lastName, Email: $email, Age: $age, JobTitle: $jobTitle, File: $file})↵}↵"变量:年龄:1977-04-04"电子邮件:JhoneDoe@hotmail.com"文件:文件 {name: "something.jpg", lastModified: 1589557760497, lastModifiedDate: Fri May 15 2020 17:49:20 GMT+0200 (centraleuropeisk sommartid), webkitRelativePath: "", size: }32355, ...名字:约翰"职位名称:很酷的东西"姓氏:母鹿"密码:CoolPassword!"123__proto__:对象__proto__:对象

在浏览器中发送的查询:

后端接收数据但不包括图像:

最近发现我的 fastify 后端在读取 formData 时可能有问题.尝试安装

fastify-multipart

但注册时出错:

<块引用>

FST_ERR_CTP_ALREADY_PRESENT(contentType) ^ FastifyError[FST_ERR_CTP_ALREADY_PRESENT]:

之后我尝试了:

npm uninstall fastify-file-upload

错误仍然存​​在.

解决方案

这需要一些时间,通常当您认为某些事情是理所当然的时,就需要时间来发现错误.

对于遇到同样问题的任何人,请记住您添加内容的顺序很重要!

我做了什么:

const Fdata = new FormData();Fdata.append('0', fileImp.file);//注意这个Fdata.append('操作', JSON.stringify(obj.data));const map = {//注意这个'0': ['variables.file'],};Fdata.append('map', JSON.stringify(map));

问题:还记得我说过添加事物的顺序很重要吗?那么这里的情况是在添加文件之后添加了映射.

正确的做法:

const Fdata = new FormData();Fdata.append('操作', JSON.stringify(obj.data));const map = {//注意这个'0': ['variables.file'],};Fdata.append('map', JSON.stringify(map));Fdata.append('0', fileImp.file);//注意这个

另请注意,在我的问题中,我错过了在变量中将文件本身设置为 null:

 变量:{文件:空,},

这是必须的.

有关更多信息阅读此处

When sending images via axios I found I have to use formdata. I add my images here but when sending the formdata my entire backend just freezes, just says "pending".

Ive been following this

And my attempt so far:

backend:

Apollo:

import { ApolloServer, makeExecutableSchema } from 'apollo-server-fastify';

const schema = makeExecutableSchema({ typeDefs, resolvers });

const apolloServer = new ApolloServer({
  schema,
  uploads: {
    maxFileSize: 10000000,
    maxFiles: 5,
  },
});

(async function() {
  app.register(apolloServer.createHandler({ path: '/api' }));
})();

schema:

  scalar DateTime
  scalar Upload

  input addUser {
    Email: String!
    Password: String
    FirstName: String!
    LastName: String!
    Age: DateTime!
    JobTitle: String!
    File: Upload
  }

  type Mutation {
    register(input: addUser!): Boolean
  }

resolver:

  Mutation: {
    register: async (obj, args, context, info) => {
        // how to get the formData?
      },
  }

FrontEnd:

I build the request like this:

const getMutation = (mutate: MutationNames, returParams?: any): any => {
  const mutation = {
    login: print(
      gql`
        mutation($email: String!, $password: String!) {
          login(email: $email, password: $password) {
            token
            refreshToken
          }
        }
      `
    ),
    register: print(
      gql`
        mutation(
          $firstName: String!
          $email: String!
          $lastName: String!
          $age: DateTime!
          $jobTitle: String!
          $file: Upload
        ) {
          register(
            input: {
              FirstName: $firstName
              LastName: $lastName
              Email: $email
              Age: $age
              JobTitle: $jobTitle
              File: $file
            }
          )
        }
      `
    ),

  }[mutate];

  if (!mutation) return {};

  return mutation;
};

In this case im using the register mutation.

I have a few hooks on how I handle the data fetching so Im not going to include it since it is alot of code. The data is fetched correctly in the front end and before posting to the backend im putting everything to a formData object:

  const submitForm: SubmitForm = (obj: SendObject) => {
    const Fdata = new FormData();

    Fdata.append('0', fileImp.file);

    Fdata.append('operations', JSON.stringify(obj.data));

    const map = {
      '0': ['variables.file'],
    };
    Fdata.append('map', JSON.stringify(map));

    callAxiosFn(
      {
        method,
        url: 'http://localhost:4000/api',
        data: Fdata,
        // headers: obj.headers,
      },
      qlType.toString()
    );
  };

gets called like this:

  const response = await axios({
    headers: {
      Accept: 'application/json',
      'x-token': localStorage.getItem('token'),
      'x-refresh-token': localStorage.getItem('refreshToken'),
      ...(config.headers || {}),
    },
    ...config,
  });

config is AxiosRequestConfig

What Im sending:

I dont exactly understand How the formdata will hit my resolver endpoint and for that reason im doing something wrong since the backend returns:

(node:748) UnhandledPromiseRejectionWarning: [object Array] (node:748) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1) (node:748) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

I realize this is alot but Im at the end of my vits here, been at this the entire day. Any help is deeply appreciated.

EDIT:

Since my backend was questioned I thought I would just show that when sending data without appending Formdata like I do above then I get it working:

  const submitForm: SubmitForm = (obj: SendObject) => {

    callAxiosFn(
      {
        method,
        url: 'http://localhost:4000/api',
        data: obj.data,
      },
      qlType.toString()
    );
  };

obj.data is:

{query: "mutation ($firstName: String!, $email: String!, $l… Age: $age, JobTitle: $jobTitle, File: $file})↵}↵", variables: {…}}
query: "mutation ($firstName: String!, $email: String!, $lastName: String!, $age: DateTime!, $jobTitle: String!, $file: Upload) {↵  register(input: {FirstName: $firstName, LastName: $lastName, Email: $email, Age: $age, JobTitle: $jobTitle, File: $file})↵}↵"
variables:
age: "1977-04-04"
email: "JhoneDoe@hotmail.com"
file: File {name: "something.jpg", lastModified: 1589557760497, lastModifiedDate: Fri May 15 2020 17:49:20 GMT+0200 (centraleuropeisk sommartid), webkitRelativePath: "", size: 32355, …}
firstName: "Jhon"
jobTitle: "SomethingCool"
lastName: "Doe"
password: "CoolPassword!"123"
__proto__: Object
__proto__: Object

query getting sent in the browser:

Backend reciving the data but the image is not included:

EDIT:

Recently found that my fastify backend might have issues with reading formData. tried installing

fastify-multipart

but got errors when registering it:

FST_ERR_CTP_ALREADY_PRESENT(contentType) ^ FastifyError [FST_ERR_CTP_ALREADY_PRESENT]:

After that I tried:

npm uninstall fastify-file-upload

Error remained.

解决方案

This took some time and usally when you take something for granted it takes time to find the mistake.

For anyone having the same problem please remember that the order you add something MATTERS!

What I did:

const Fdata = new FormData();

Fdata.append('0', fileImp.file);  // NOTICE THIS

Fdata.append('operations', JSON.stringify(obj.data));

const map = { // NOTICE THIS
  '0': ['variables.file'],
};
Fdata.append('map', JSON.stringify(map));

Problem: Remember when I said order of appending things matter? Well the case here was that the mapping was added after the file was added.

The correct way:

const Fdata = new FormData();

Fdata.append('operations', JSON.stringify(obj.data));

const map = { // NOTICE THIS
  '0': ['variables.file'],
};
Fdata.append('map', JSON.stringify(map));
Fdata.append('0', fileImp.file);  // NOTICE THIS

Also note that in my qestion I missed setting the file itself to null in the variables:

  variables: {
    file: null,
  },

This has to be done.

For more info read here

这篇关于如何使用 axios 上传图像到 fastify + graphql 后端?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆