首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何上传图片,以便使用axios来美化+ graphql后端?

如何上传图片,以便使用axios来美化+ graphql后端?
EN

Stack Overflow用户
提问于 2020-05-15 19:36:03
回答 3查看 2K关注 0票数 1

当通过axios发送图像时,我发现我必须使用格式数据。我在这里添加我的图像,但是当发送格式数据时,我的整个后端只是冻结,只是说“挂起”。

我一直在跟踪

到目前为止我的尝试是:

后端:

阿波罗:

代码语言:javascript
复制
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' }));
})();

模式:

代码语言:javascript
复制
  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:

代码语言:javascript
复制
  Mutation: {
    register: async (obj, args, context, info) => {
        // how to get the formData?
      },
  }

FrontEnd:

我提出这样的请求:

代码语言:javascript
复制
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;
};

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

我有一些关于如何处理数据抓取的钩子,所以我不会包含它,因为它是大量的代码。数据在前端被正确获取,在提交到后端im之前,将所有内容都放到formData对象中:

代码语言:javascript
复制
  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()
    );
  };

会像这样被调用:

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

配置为AxiosRequestConfig

我发送的内容:

我不太明白格式化数据将如何到达我的解析器端点,为此,我做了一些错误的事情,因为后端返回:

(节点:748) UnhandledPromiseRejectionWarning:目标阵列 UnhandledPromiseRejectionWarning:未处理的承诺拒绝。此错误起源于在异步函数中抛出而不带catch块,或者拒绝使用.catch()处理的承诺。(拒绝id: 1) (节点:748) DEP0018 DeprecationWarning:未处理的承诺拒绝被取消。在未来,承诺不处理的拒绝将使用非零退出代码终止Node.js进程。

我意识到这不算什么,但我在这里的最后,一整天都在这里。任何帮助都是非常感谢的。

编辑:

由于我的后端受到了质疑,我想我应该像上面一样,在发送数据时不附加Formdata,这样我就可以让它正常工作:

代码语言:javascript
复制
  const submitForm: SubmitForm = (obj: SendObject) => {

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

obj.data是:

代码语言:javascript
复制
{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的问题。试装

代码语言:javascript
复制
fastify-multipart

但是注册时出现了错误:

FST_ERR_CTP_ALREADY_PRESENT(contentType) ^ FastifyError FST_ERR_CTP_ALREADY_PRESENT:

在那之后,我试着:

代码语言:javascript
复制
npm uninstall fastify-file-upload

错误依然存在。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2020-05-19 16:04:20

这需要一些时间,而通常情况下,当你认为某件事是理所当然的时,就需要时间去发现错误。

对于任何有相同问题的人,请记住,您添加的命令很重要!

我所做的:

代码语言:javascript
复制
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));

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

正确的方法:

代码语言:javascript
复制
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

还请注意,在我的质量管理中,我忽略了在变量中将文件本身设置为null:

代码语言:javascript
复制
  variables: {
    file: null,
  },

必须这样做。

有关更多信息,在这里读

票数 1
EN

Stack Overflow用户

发布于 2020-05-15 19:44:28

嗯,我还没有探讨过这个话题。但是我知道axiosGraphQL并不是很好地工作。Axios主要用于REST 调用。然而,我真的很喜欢并且已经从这个频道本·阿瓦德学到了很多东西。这家伙真的很棒,很清楚很好地解释了事情。但最重要的是,他是一个GraphQL爱好者,探索并介绍了有关它的各种主题,以及与React.jsTypeORM & PostgreSQL。这里有一些有用的链接,从他的频道,可能有助于您的问题:

我希望这能帮到你!如果内容有帮助,请告诉我!

票数 1
EN

Stack Overflow用户

发布于 2020-05-29 12:47:11

@CodingLittle喜悦您发现答案与多部分表单字段排序有关。

一些需要添加的内容(尽管我是graphql-upload作者,但我没有对您的回答发表评论所需的50项声誉)…

还请注意,在我的质量管理中,我没有在变量中将文件本身设置为null。

这是正确的,而且很好,尽管在现实中,许多GraphQL多部分请求规范服务器实现将简单地用上传标量值替换文件映射路径上的任何内容,而不关心存在什么--理论上,您可以用asdf而不是null替换变量中的文件,而且它仍然可以工作。JSON.stringify会用类似于{}的东西替换文件实例。

如果后端以明确的400状态和描述性错误消息进行响应,而不是抛出一个严重的UnhandledPromiseRejectionWarning错误,那么您本来可以避免很多麻烦。如果您的graphql-upload依赖关系在后端是最新的,那么当请求不符合GraphQL多部分请求规范有关字段排序的要求时,您应该看到一个描述性错误消息,就像在graphql-upload测试中所看到的那样:

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

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

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61827041

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档