{"id":14606,"library":"graphql-server-express-upload","title":"GraphQL Express File Upload Middleware","description":"The `graphql-server-express-upload` package provides a middleware for Express.js applications to facilitate file uploads within GraphQL endpoints. Released with version 1.0.0 in 2016, it was designed to integrate specifically with `graphql-server-express` and relies on `multer` for parsing `multipart/form-data` requests. On the client-side, it required companion libraries like `apollo-upload-network-interface` because standard Apollo Client versions at the time did not natively support file uploads. This package introduced an `UploadedFile` scalar and expected a specific resolver implementation. However, both `graphql-server-express` and this package are now considered abandoned, with no updates since their initial release. Modern GraphQL ecosystems, particularly `@apollo/server`, have built-in, more robust file upload capabilities (often leveraging `graphql-upload`), making this package largely obsolete and incompatible with contemporary GraphQL server setups.","status":"abandoned","version":"1.0.0","language":"javascript","source_language":"en","source_url":"https://github.com/HriBB/graphql-server-express-upload","tags":["javascript","apollo","graphql","server","express","file","upload","middleware"],"install":[{"cmd":"npm install graphql-server-express-upload","lang":"bash","label":"npm"},{"cmd":"yarn add graphql-server-express-upload","lang":"bash","label":"yarn"},{"cmd":"pnpm add graphql-server-express-upload","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Required for parsing multipart/form-data requests containing file uploads.","package":"multer","optional":false},{"reason":"This middleware is specifically designed to function as an enhancement for graphql-server-express, which is now deprecated.","package":"graphql-server-express","optional":false},{"reason":"Used for GraphQL schema definition, type parsing (e.g., Kind enum in resolvers), and core GraphQL functionality.","package":"graphql","optional":false}],"imports":[{"note":"This is a default export. For CommonJS, use `const graphqlExpressUpload = require('graphql-server-express-upload').default;`.","wrong":"import { graphqlExpressUpload } from 'graphql-server-express-upload';","symbol":"graphqlExpressUpload","correct":"import graphqlExpressUpload from 'graphql-server-express-upload';"},{"note":"This is a GraphQL Schema Definition Language (SDL) scalar type, not a JavaScript import. It must be defined in your `.graphql` files or `typeDefs` string.","symbol":"UploadedFile","correct":"scalar UploadedFile"},{"note":"The `Kind` enum is used within the example `parseJSONLiteral` resolver function to identify GraphQL AST node types. It's imported from the main `graphql` package.","wrong":"import { Kind } from 'graphql/language/kinds';","symbol":"Kind","correct":"import { Kind } from 'graphql';"}],"quickstart":{"code":"import express from 'express';\nimport { makeExecutableSchema } from '@graphql-tools/schema';\nimport { graphqlExpress, graphiqlExpress } from 'graphql-server-express';\nimport graphqlExpressUpload from 'graphql-server-express-upload';\nimport multer from 'multer';\nimport { Kind } from 'graphql';\n\nconst app = express();\nconst port = 4000;\n\n// Multer setup for file uploads\nconst upload = multer({\n  dest: '/tmp/uploads', // Ensure this directory exists or create it\n});\n\n// GraphQL Schema Definition\nconst typeDefs = `\n  scalar UploadedFile\n\n  type ProfilePicture {\n    id: Int!\n    url: String\n    thumb: String\n    square: String\n    small: String\n    medium: String\n    large: String\n    full: String\n  }\n\n  type Query {\n    hello: String\n  }\n\n  type Mutation {\n    uploadProfilePicture(id: Int!, files: [UploadedFile!]!): ProfilePicture\n  }\n`;\n\n// Utility for UploadedFile scalar resolver (as shown in package README)\nfunction parseJSONLiteral(ast) {\n  switch (ast.kind) {\n    case Kind.STRING:\n    case Kind.BOOLEAN:\n      return ast.value;\n    case Kind.INT:\n    case Kind.FLOAT:\n      return parseFloat(ast.value);\n    case Kind.OBJECT: {\n      const value = Object.create(null);\n      ast.fields.forEach(field => {\n        value[field.name.value] = parseJSONLiteral(field.value);\n      });\n      return value;\n    }\n    case Kind.LIST:\n      return ast.values.map(parseJSONLiteral);\n    default:\n      return null;\n  }\n}\n\n// GraphQL Resolvers\nconst resolvers = {\n  UploadedFile: {\n    __parseLiteral: parseJSONLiteral,\n    __serialize: value => value,\n    __parseValue: value => value,\n  },\n  Query: {\n    hello: () => 'Hello from GraphQL!',\n  },\n  Mutation: {\n    async uploadProfilePicture(root, { id, files }, context) {\n      console.log('Received upload for profile picture:', { id, files });\n      // 'files' here would be an array of objects provided by Multer/graphqlExpressUpload\n      // In a real app, process these files (e.g., save to disk, cloud storage).\n      const uploadedFile = files[0]; // Example: assuming one file\n      return {\n        id,\n        url: `http://example.com/uploads/${uploadedFile?.filename || 'dummy.jpg'}`,\n        thumb: `http://example.com/thumbs/${uploadedFile?.filename || 'dummy.jpg'}`,\n        square: `http://example.com/square/${uploadedFile?.filename || 'dummy.jpg'}`,\n        small: `http://example.com/small/${uploadedFile?.filename || 'dummy.jpg'}`,\n        medium: `http://example.com/medium/${uploadedFile?.filename || 'dummy.jpg'}`,\n        large: `http://example.com/large/${uploadedFile?.filename || 'dummy.jpg'}`,\n        full: `http://example.com/full/${uploadedFile?.filename || 'dummy.jpg'}`\n      };\n    },\n  },\n};\n\nconst schema = makeExecutableSchema({ typeDefs, resolvers });\n\n// Express app setup for GraphQL endpoint\napp.use(\n  '/graphql',\n  upload.array('files'), // Multer middleware to handle 'files' input field\n  graphqlExpressUpload({ endpointURL: '/graphql' }), // THIS PACKAGE'S MIDDLEWARE\n  graphqlExpress((req) => ({\n    schema,\n    context: {\n      req, // Access to the original request\n    },\n  }))\n);\n\n// GraphiQL endpoint for testing\napp.use(\n  '/graphiql',\n  graphiqlExpress({\n    endpointURL: '/graphql',\n  })\n);\n\napp.listen(port, () => {\n  console.log(`Server running on http://localhost:${port}`);\n  console.log(`GraphQL endpoint: http://localhost:${port}/graphql`);\n  console.log(`GraphiQL endpoint: http://localhost:${port}/graphiql`);\n});","lang":"javascript","description":"Demonstrates setting up an Express server with `graphql-server-express-upload`, configuring `multer` for multipart processing, defining the `UploadedFile` scalar in the schema, and providing its custom resolver."},"warnings":[{"fix":"Do not use this package in new projects. For existing applications, migrate to `@apollo/server` and utilize its built-in file upload capabilities or consider `graphql-upload` with other GraphQL server implementations.","message":"This package is built for `graphql-server-express`, which is deprecated. It is fundamentally incompatible with modern Apollo Server versions (@apollo/server) and recent GraphQL.js versions (v15+). Attempting to use it will likely result in critical runtime errors.","severity":"breaking","affected_versions":">=1.0.0"},{"fix":"Avoid using this package. If bound to an existing legacy system, plan a migration path away from `graphql-server-express` and its associated ecosystem.","message":"The underlying `graphql-server-express` library, for which this package was developed, is deprecated and no longer maintained. Consequently, `graphql-server-express-upload` also inherits this deprecated status.","severity":"deprecated","affected_versions":"1.0.0"},{"fix":"Ensure `multer` middleware (e.g., `upload.array('files')`) is placed directly before `graphqlExpressUpload` in your Express middleware chain and that the `upload.array` or `upload.single` field name matches the client-side input name for files.","message":"This middleware requires explicit integration with `multer` for `multipart/form-data` parsing *before* `graphqlExpressUpload`. Incorrect `multer` configuration (e.g., wrong field name for files, missing destination) will prevent file uploads from being processed correctly.","severity":"gotcha","affected_versions":"1.0.0"},{"fix":"Implement custom logic within your GraphQL mutation resolver to take the `files` argument (which will contain `multer`'s file objects) and perform actions like saving to disk, uploading to cloud storage, or further processing.","message":"The `UploadedFile` scalar resolver provided in the documentation is a basic JSON parser. It does not inherently handle file storage or processing; it merely makes the processed file metadata (from `multer`) available in your GraphQL mutation's `files` argument.","severity":"gotcha","affected_versions":"1.0.0"}],"env_vars":null,"last_verified":"2026-04-19T00:00:00.000Z","next_check":"2026-07-18T00:00:00.000Z","problems":[{"fix":"Ensure `multer` middleware (e.g., `upload.array('files')`) is applied *before* `graphqlExpressUpload`, and `graphqlExpressUpload` is *before* `graphqlExpress`. Also, verify the `endpointURL` configuration matches your GraphQL endpoint path.","cause":"The `graphqlExpressUpload` middleware or `multer` is not correctly placed or configured in the Express middleware chain, preventing the GraphQL query from being parsed.","error":"TypeError: Cannot read properties of undefined (reading 'query') / req.body.query is undefined"},{"fix":"Add `scalar UploadedFile` to your GraphQL schema definition (typeDefs) and ensure the `UploadedFile` resolver (with `__parseLiteral`, `__serialize`, `__parseValue` methods) is correctly provided to your GraphQL server setup.","cause":"The `UploadedFile` scalar type has not been defined in your GraphQL schema or its associated resolver is missing or incorrectly registered with your GraphQL server.","error":"Unknown type 'UploadedFile'. Did you mean 'Upload'? (or similar type system errors)"},{"fix":"Verify that your client-side code uses a network interface (e.g., `apollo-upload-network-interface` for older Apollo Client versions, or modern `apollo-link-http` with `apollo-upload-client`) that correctly handles `multipart/form-data`. Additionally, double-check the `UploadedFile` resolver logic for any issues.","cause":"The client-side is not sending files in the expected `multipart/form-data` format, or the `UploadedFile` scalar resolver is misconfigured, leading to a type mismatch during validation.","error":"ApolloError: Variable \"$files\" got invalid value [object Object]; Expected type UploadedFile! (or similar type mismatch for file arguments)"}],"ecosystem":"npm"}