createReadStream() throwing RangeError: Maximum call stack size exceeded when uploading file

createReadStream() throwing RangeError: Maximum call stack size exceeded when uploading file

我正在尝试使用 Apollo Server 的 Upload 标量直接将文件发送到 S3。我的架构:

const { gql } = require('apollo-server-express')

module.exports = gql`

extend type Mutation {
  createPicture(
    name: String!
    picture: Upload!
  ): Picture!
}

type Picture {
  name: String!
  picture: String!
}
`

解析器:

const { combineResolvers } = require('graphql-resolvers')
const isAuthenticated = require('./auth')
const { uploadPhoto } = require('../services/picture')

module.exports = {
  Mutation: {
    createPicture: combineResolvers(
      isAuthenticated,
      async (
        parent,
        { name, picture = null },
        { models, me }
      ) => {
        const { createReadStream, filename, mimetype, encoding } = await picture
        // Does not get past this line
        const stream = createReadStream()

        uploadPhoto(stream, filename)

        const pictureModel = models.Picture.create({
           name,
           picture
        })
        return pictureModel
      }
    )
  }
}

但是我的代码错误是这样的:

internal/util.js:55
  function deprecated(...args) {
                     ^

RangeError: Maximum call stack size exceeded
    at ReadStream.deprecated [as open] (internal/util.js:55:22)
    at ReadStream.open ([truncated]/node_modules/fs-capacitor/lib/index.js:90:11)
    at _openReadFs (internal/fs/streams.js:123:12)
    at ReadStream.<anonymous> (internal/fs/streams.js:116:3)
    at ReadStream.deprecated [as open] (internal/util.js:70:15)
    at ReadStream.open ([truncated]/node_modules/fs-capacitor/lib/index.js:90:11)
    at _openReadFs (internal/fs/streams.js:123:12)
    at ReadStream.<anonymous> (internal/fs/streams.js:116:3)
    at ReadStream.deprecated [as open] (internal/util.js:70:15)
    at ReadStream.open ([truncated]/node_modules/fs-capacitor/lib/index.js:90:11)
    at _openReadFs (internal/fs/streams.js:123:12)
    at ReadStream.<anonymous> (internal/fs/streams.js:116:3)
    at ReadStream.deprecated [as open] (internal/util.js:70:15)
    at ReadStream.open ([truncated]/node_modules/fs-capacitor/lib/index.js:90:11)
    at _openReadFs (internal/fs/streams.js:123:12)
    at ReadStream.<anonymous> (internal/fs/streams.js:116:3)
    at ReadStream.deprecated [as open] (internal/util.js:70:15)
    at ReadStream.open ([truncated]/node_modules/fs-capacitor/lib/index.js:90:11)
    at _openReadFs (internal/fs/streams.js:123:12)
    at ReadStream.<anonymous> (internal/fs/streams.js:116:3)
    at ReadStream.deprecated [as open] (internal/util.js:70:15)
    at ReadStream.open ([truncated]/node_modules/fs-capacitor/lib/index.js:90:11)

注意:我确信图像发送正确,因为 filename 是正确的

原来这是 this graphql-upload 中的错误。降级到节点 12 并已修复(此处列出的解决方案对我没有帮助)

我在节点版本 14 中也出现了这个错误! 我是这样解决的:

  1. 安装最新版本的 graphql-upload!

  2. 使用 graphqlUploadExpress 中间件定义最大文件限制。

    import { graphqlUploadExpress } from "graphql-upload";
    const app = express()
    app.use(graphqlUploadExpress({ maxFileSize: 1000000000, maxFiles: 10 }));
    
  3. 在初始化 ApolloServer 时将上传设置为 false

      const server = new ApolloServer({
        uploads: false,
        schema,
      });
    

将此添加到 package.json:

"resolutions": {
    "**/**/fs-capacitor":"^6.2.0",
    "**/graphql-upload": "^11.0.0"
  }

来源:https://github.com/jaydenseric/graphql-upload/issues/170#issuecomment-641938198

使用:

    "apollo-server": "^2.18.2",
    "apollo-server-express": "2.18.2",
    "aws-sdk": "^2.771.0",
    "express-fileupload": "^1.2.0",
    "graphql": "^15.3.0",
    "graphql-upload": "^11.0.0",
    "fs-capacitor": "^6.2.0",

我通过安装最新的 fs-capacitor 作为依赖来解决这个问题

yarn add fs-capacitor

将此添加到您的 package.json

 "resolutions": {
    "graphql-upload": "^11.0.0"
  }

然后在脚本中添加这个

"scripts": {
    ....
    "preinstall": "npx npm-force-resolutions", //This one
    ....
}

然后你需要执行 npm install。完成

来源:graphql-upload

我已经多次处理这个问题

问题是旧的 graphql-upload 版本 8 更准确地使用节点打开流功能,该功能已弃用,在 13.x 和更旧的节点版本中不再可用。

所以解决方案是您可以使用 nvm 将节点版本设置为 12 或使用 package.json 文件中的分辨率。 第一个解决方案(在你最喜欢的终端):

nvm install 12; nvm use 12

第二个解决方案(在package.json):

"resolutions": {
    "**/**/fs-capacitor":"^6.2.0",
    "**/graphql-upload": "^11.0.0"
  }

这也是我几个月来一直在处理的问题,我认为 apollo 团队真的不喜欢更新他们的依赖项。

因为它是 fs-capacitor 的一个错误,这将有助于我们在这个 issue

中看到

在节点 14.16.1 中为我工作,配置如下:

"resolutions": {
    "fs-capacitor": "^6.2.0",
    "graphql-upload": "^11.0.0"
}

我需要在“脚本”中添加强制分辨率

"scripts": {
    ....
    "preinstall": "npx npm-force-resolutions"
}

删除 ./node_modules 并使用 npm install 再次安装依赖项。

我已阅读 graphql-upload 文档,但找不到一个可靠的示例来说明如何在 NodeJS 14 上将图形上传与 apollo-server 结合使用。 基于示例应用程序(在旧的 graphql-upload 版本的 apollo-server 上运行,在 NodeJS 14 上失败)和堆栈溢出的答案,我设法创建了一个功能齐全的示例。

原例子:https://github.com/DNature/apollo-upload

我使用了 apollo-server-express,而不是 apollo-server。

使用 NodeJS 14、graphql-upload@12.0.0 和 apollo-server-express@2.25.1:

index.js

import { ApolloServer } from "apollo-server-express";
import express from "express";
import { graphqlUploadExpress } from "graphql-upload";
import typeDefs from "./typeDefs";
import resolvers from "./resolvers";

// Import your database configuration
import connect from "./db";

export default (async function () {
  try {
    await connect.then(() => {
      console.log("Connected  To MongoDB Successfully");
    });

    const server = new ApolloServer({
      uploads: false, // Disables the bundled ApolloServer old graphql-upload that doesn't work on NodeJS 14
      typeDefs,
      resolvers,
    });
    await server.start();

    const app = express();
    app.use(graphqlUploadExpress({ maxFileSize: 1000000000, maxFiles: 10 }));
    server.applyMiddleware({ app });

    await new Promise((resolve) => app.listen({ port: 7000 }, resolve));
    console.log(
      ` Server ready at http://localhost:7000${server.graphqlPath}`
    );
  } catch (err) {
    console.error(err);
  }
})();

在typeDefs.gql中需要定义标量上传:

import { gql } from "apollo-server-express";

export default gql`
  scalar Upload

  type File {
    id: ID!
  ...

在 resolvers.js 中,需要定义上传的解析器:

...

import { GraphQLUpload } from 'graphql-upload';

...

export default {
  Upload: GraphQLUpload,

  Query: {
    hello: () => "Hello world"
  },
  Mutation: {
...

终于从邮递员上传:

Note: the key 0 is of type File, not Text!

TLDR:默认的 Apollo 服务器文件上传在节点 >=13 中不起作用。通过使用 graphql-upload 服务器文件上传

覆盖 Apollo 的服务器文件上传来修复它

npm install graphql-upload

覆盖 TypeDefs

中的默认 Apollo 上传类型

const typeDefs = gql`
  scalar Upload
  ...
 `

覆盖 index.js

中的默认 Apollo 上传类型

const { GraphQLUpload } = require('graphql-upload')
const { graphqlUploadExpress } = require('graphql-upload')
const express = require('express')
 
const app = express()

app.use(graphqlUploadExpress({ 
  maxFileSize: 10000000, 
  maxFiles: 10 
}))

const server = new ApolloServer({
  typeDefs,
  resolvers: {
    Upload: GraphQLUpload,
    ...resolvers
  }
  uploads: false
  ...
})

server.applyMiddleware({
  app
})