graphql: File uploads not working with graphql-upload package
I’m submitting a…
[ ] Regression
[x] Bug report
[ ] Feature request
[ ] Documentation issue or request
[ ] Support request
Current behavior
I was going through tutorials on how to use NestJS with graphql. I wanted to create a mutation to upload a file to the server. I utilized the graphql-upload package to handle this per this NestJS tutorial: https://stephen-knutter.github.io/2020-02-07-nestjs-graphql-file-upload/
When you request the mutation as displayed in the tutorial, the request returns an error not liking the null value in the operation. It seems the GraphQL validators are running too soon not allowing an interceptor or resolver to handle the request.
It is possible this error is in a lower level dependancy or a miss configuration within Nest. I am unsure.
Expected behavior
I should be able to recieve the file within my resolver using graphql-upload package in my resolver.
Minimal reproduction of the problem with instructions
Clone the following Repo, install dependacies, and start dev. Try creating the CURL request or use the postman request showin in the tutorial: https://stephen-knutter.github.io/2020-02-07-nestjs-graphql-file-upload/
Error Reproduction: https://github.com/aaronhawkey48/gqlupload-error
What is the motivation / use case for changing the behavior?
This should be fixed because it is breaking file uploads within nest.
Environment
Nest version :7.0.0
Nestjs/graphql: 7.3.11
graphql-upload: 11.0.0
For Tooling issues:
- Node version: v12.13.0
- Platform: Mac, Windows
Others:
NA
About this issue
- Original URL
- State: closed
- Created 4 years ago
- Comments: 28 (5 by maintainers)
For any future readers, here is how to fix the issue once and for all.
The problem is that @nestjs/graphql’s dependency, apollo-server-core, depends on an old version of graphql-upload (v8.0) which has conflicts with newer versions of Node.js and various packages. Apollo Server v2.21.0 seems to have fixed this but @nestjs/graphql is still on v2.16.1. Furthermore, Apollo Server v3 will be removing the built-in graphql-upload.
The solution suggested in this comment is to disable Apollo Server’s built-in handling of uploads and use your own. This can be done in 3 simple steps:
1. package.json
Remove the fs-capacitor and graphql-upload entries from the resolutions section if you added them, and install the latest version of graphql-upload (v11.0.0 at this time) package as a dependency.
2. src/app.module.ts
Disable Apollo Server’s built-in upload handling and add the graphqlUploadExpress middleware to your application.
3. src/blog/post.resolver.ts (example resolver)
Remove the GraphQLUpload import from apollo-server-core and import from graphql-upload instead
Note that there is an upstream problem with
graphql-upload(and/orapollo-server-express) when used with node 13 (probably 14 too). See: https://github.com/jaydenseric/graphql-upload/issues/170#issuecomment-562759227I had the same issues, and was able to resolve it like this:
Also I added this in
package.json, as per the linked issue above:Edit: @msheakoski fixed up their example above, have a look. 👆
If you’d like an example that encapsulates the logic in a reusable module, keep reading:
~I tried @msheakoski’s great suggestion - mostly worked! But the middleware needs to be applied to the same path as the GraphQLModule (so, not globally).~
Replaced Step 2. with something like:
graphql-with-upload.module.tsapp.module.tsGraphQLWithUploadModule” inapp.module.ts- thanks @felinto-dev!Good jobs guys ❤️ @msheakoski @loklaan
I didn’t understand how to apply the solution shown here the first time, so after some trial and error, I got it. I hope you can help someone.
@loklaan I couldn’t understand why you import “GraphQLWithUploadModule” in this file if you don’t use it.
This is what worked for me followed by what was shown above:
app.module.ts
file.resolver.ts
PS: You need to create a folder called “uploads” at the root of your application, or it will trigger an error.
cheers 🍕😍
Thanks it works, but I wish we wouldn’t have to implement our own upload middleware for such a basic feature. I hope it gets fixed soon to work out of the box.
@loklaan I actually spoke a bit to @jmcdo29 a bit on this issue. Made a reproduction of the issue: https://github.com/luke-cbs/nestjs-upaload-reproduction
This does not use the above solution but actually uses resolutions of the fs-capacitor module. However we noticed although the error was gone and uploading text files and other simple types worked correctly. A new issue comes in when uploading images. These then seem to hang the request.
There seems to be some issues that @msheakoski eluded to quite well with Apollo + graphql-upload and then NestJS seems to be caught in all this as a result of other issues.
The end result is I created a REST API endpoint to handle uploads until such time something like these uploads works consistently.
It is an interesting note that this approach is also suggested in @apollographql/graphql-upload-8-fork that apollo-server-core uses. All the more reasons to go with your approach, @msheakoski
Good catch, @loklaan! I missed that part of the graphql-upload instructions. I updated the “app.use()” with your path suggestion to keep the example simple.
I also like your approach because it keeps the middleware config together with the GraphQLModule config!
I was using the resolutions approach on node v14.15 (downgrading fs-capacitor and graphql-upload), but i keep getting issue with the createReadStream’s finish event not emitted, and the stream keep getting closed prematurely resulting in broken image and promise not resolved properly.
@msheakoski’s solution (https://github.com/nestjs/graphql/issues/901#issuecomment-780007582 ) worked for me with a tiny adjustment to my solutions which used schema first method.
before i made the adjustment i keep getting createReadStream is not a function error, look like the file object wasn’t passed into my resolver.
Here is my trimmed package.json to show the version i am using.
Hope this help someone somewhere.
Hey thanks for the snippet. while running that code, I’m getting
POST body missing. Did you forget use body-parser middleware?error whenever I tried to run a muatation that got a file upload. Do you have any idea why this is happening?It seems that (as I’ve initially mentioned), this issue isn’t specifically related to NestJS. Please, use our Discord channel (support) for such questions. We are using GitHub to track bugs, feature requests, and potential improvements.
@kamilmysliwiec I did and they said to open this issue because there is a bug per a core team member jmcdo29. This is a bug report.