当前位置: 首页 > 知识库问答 >
问题:

如何上传图像,以法术与axios图形后端?

仉伟兆
2023-03-14

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

我一直在关注这个

到目前为止,我的尝试是:

后端:

阿波罗:

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' }));
})();

模式

  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
  }

解析程序:

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

前端:

我构建如下请求:

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;
};

在这种情况下,我使用寄存器突变。

我有一些关于如何处理数据获取的钩子,所以我不打算包括它,因为它是很多代码。在前端正确地获取数据,并在发布到后端之前,将所有内容放入formData对象:

  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()
    );
  };

被称为如下:

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

配置为:

我发送的内容:

我不太明白formdata是如何命中我的解析器endpoint的,因此我做了一些错误的事情,因为后端返回:

(节点:748)未处理的PromisejectionWarning:[对象数组](节点:748)未处理的PromisejectionWarning:未处理的promise拒绝。此错误源于在没有catch块的情况下抛出异步函数的内部,或者拒绝使用未处理的promise。catch()。(拒绝id:1)(节点:748)[DEP0018]弃用警告:未处理的promise拒绝已弃用。将来,未处理的promise拒绝将终止节点。具有非零退出代码的js进程

我知道这是很多,但我在这里已经结束了,一整天都在做这个。任何帮助都深为感激。

编辑:

由于我的后端被质疑,我想我只会显示,当发送数据时,不附加Formdata,就像我在上面做的那样,然后我得到它的工作:

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

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

obj.data是:

{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

在浏览器中发送查询:

编辑:

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

fastify-multipart

但注册时出现错误:

FST_ERR_CTP_ALREADY_PRESENT(ContentType)^FastifyError[FST_ERR_CTP_ALREADY_PRESENT]:

在那之后,我尝试:

npm uninstall fastify-file-upload

错误依然存在。

共有3个答案

夏知
2023-03-14

@codingLittle很高兴你发现答案与多部分表单字段排序有关。

还有一些需要补充的内容(尽管我是graphql上传的作者,但我没有对你的答案发表评论所需的50%声誉,所以我需要回答)…

还要注意,在我的qestion中,我没有在变量中将文件本身设置为null

这是正确的,尽管实际上很多GraphQL multipart request spec服务器实现都会简单地用上载标量值替换文件映射路径上的任何内容,而不关心其中的内容-理论上,您可以将变量中的文件替换为asdf,而不是null,它仍然可以工作<代码>JSON。stringify会用类似{}的内容替换文件实例。

如果后端以清晰的400状态和描述性错误消息响应,而不是抛出一个粗糙的UnhandledPromiseRejtionWarning错误,那么您的许多头痛问题都可以避免。如果您的GraphQL上传依赖项在后端是最新的,那么当请求不符合GraphQL多部分请求规范关于字段排序时,您应该会看到一条描述性错误消息,如GraphQL上传测试:

https://github.com/jaydenseric/graphql-upload/blob/v11.0.0/test/public/processRequest.test.js#L929

尝试在您的后端项目中运行npm ls Graphql上传,以检查仅安装了一个版本,并且它是最新发布到npm的版本(在回答此问题时为v11)。请注意,如果您依赖阿波罗服务器为您安装它,他们使用非常过时的版本(v8)。

轩辕源
2023-03-14

这需要一些时间,通常当你认为某事是理所当然的时候,需要时间来发现错误。

对于有相同问题的人,请记住,添加内容的顺序很重要!

我所做的:

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));

问题:还记得我说过附加事物的顺序很重要吗?这里的例子是,映射是在文件添加之后添加的。

正确的方法是:

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

还要注意,在qestion中,我没有在变量中将文件本身设置为null:

  variables: {
    file: null,
  },

必须这样做。

欲了解更多信息,请阅读此处

洪凯定
2023-03-14

嗯,我还没有探讨这个话题。但我知道axios与GraphQL的结合并不是很好。Axios主要用于RESTAPI调用。然而,我真的很喜欢这个频道,并且从这个频道学到了很多东西。这家伙真是太棒了,解释得很清楚很好。但最重要的是,他是一个GraphQL爱好者,探索并提出了关于它的各种主题,以及React。js,TypeORM

  • 使用Apollo上传GraphQL中的文件
  • 如何在React中上传文件到Apollo服务器

我希望这有帮助!请让我知道内容是否有用!

 类似资料:
  • 我正试图用截击的方式发送图像 调用函数: 试道: 并传递配置文件字段中的值。 使用邮递员的成功方法:

  • 我的应用程序(Android 4.4.4)中嵌入的webview有问题。在一个页面上有一个“上传图像”按钮,我用openFileChooser管理它。 在某些设备上,当我点击webview中的“上传图像”按钮时,摄像头应用程序启动,我的应用程序被销毁。拍照后,我的应用程序被重新创建,我恢复webview状态(保存在)并调用

  • 我想首先捕获图像并将其查看到ImageView,然后单击将图像保存到FireBase。

  • 问题内容: 我要预览表单中的图像或照片,但是它不起作用,并且HTML代码如下所示: 并在下面合并了JS代码/脚本: 我的表单上有两个主要问题: 1.为什么图像或图片的预览不起作用? 2.当单击保存按钮时,如何从表单粘贴照片,它将链接到我创建的另一个PHP或PHP页面? 问题答案: 试试这个:(用于预览) 在这里工作演示>

  • 问题内容: 我已经通过Ajax提交了表单,我无法在此提交中上传图片 在提交代码中 输出: JavaScript代码 问题答案: 使用该类最简单: 因此,现在您有了一个FormData对象,准备与XMLHttpRequest一起发送。并使用FormData对象附加字段 并强制jQuery不要为您添加Content-Type标头,否则,上传文件边界字符串将丢失。

  • 问题内容: 我有一个图像,我想使用Volley库将该图像上传到我的Web服务,问题是我正在寻找一种方法,但仍然没有找到。 我找到了,但是对我不起作用:http : //develop-for- android.blogspot.com.br/2014/01/using-volley-in-your- application.html 我怎样才能做到这一点 ? 我正在尝试这个。 问题答案: 我对排球