Search code examples
apolloapollo-clientreact-apolloapollo-server

Apollo File Upload & React Apollo Upload Client, Zero Byte File


Hi I am using Node & Apollo in backend, and Apollo Upload Client in React frontend to upload file in server.

Everything is working fine, I am not getting any warning or issue but the problem is,

File which is uploaded on server, it's size is always 0 byte. I don't know what is causing this problem, so I tried by doing simple example of file upload(even this behaves same).

Sharing the simple upload example in github. React content is in Frontend folder & root folder is nodejs backend. Github Link.

I am also sharing code of simple file upload code right here if some of you don't want github

NodeJS:

const { ApolloServer, gql } = require("apollo-server");
const fs = require("fs");
const path = require("path");

const typeDefs = gql`
    type File {
        url: String!
    }

    type Query {
        hello: String!
    }

    type Mutation {
        uploadFile(file: Upload!): File!
    }
`;

const resolvers = {
    Query: {
        hello: () => "Hello World",
    },
    Mutation: {
        uploadFile: async (parent, { file }) => {
            const { createReadStream, filename, mimetype, encoding } = await file;
            const stream = createReadStream();
            const pathName = path.join(__dirname, `/public/images/${filename}`);
            await stream.pipe(fs.createWriteStream(pathName));

            return {
                url: `http://localhost:4000/images/${filename}`,
            };
        },
    },
};

const server = new ApolloServer({
    typeDefs,
    resolvers,
});

server.listen().then(({ url }) => {
    console.log(`🚀 Server ready at ${url}`);
});

React Fileupload

import React from "react";
import logo from "./logo.svg";

import { useMutation, gql } from "@apollo/client";

const UPLOAD_FILE = gql`
    mutation uploadFile($file: Upload!) {
        uploadFile(file: $file) {
            url
        }
    }
`;

const UploadForm = () => {
    const [uploadFile] = useMutation(UPLOAD_FILE, {
        onCompleted: (data) => console.log(data),
    });

    const handleFileChange = (e) => {
        const file = e.target.files[0];
        if (!file) return;
        uploadFile({ variables: { file } });
    };

    return (
        <div className="App">
            <header className="App-header">
                <img src={logo} className="App-logo" alt="logo" />
                <h1>Upload File</h1>
                <input type="file" onChange={handleFileChange} />
            </header>
        </div>
    );
};

export default UploadForm;

Setting up Apollo Upload Client(app.js)

import "./App.css";

import { ApolloClient, ApolloProvider, InMemoryCache } from "@apollo/client";
import { createUploadLink } from "apollo-upload-client";
import UploadForm from "./UploadForm";

const client = new ApolloClient({
    link: createUploadLink({
        uri: "http://localhost:4000/",
    }),
    cache: new InMemoryCache(),
});

function App() {
    return (
        <ApolloProvider client={client}>
            <UploadForm />
        </ApolloProvider>
    );
}

export default App;


Solution

  • This took me forever to find a solution when I had the same problem. This is what worked for me for anyone else who comes across this issue in the future.

    install this package: https://www.npmjs.com/package/npm-force-resolutions into server directory.

    Then write this in the package.json

    "resolutions": {
        "**/**/fs-capacitor":"3.0.0"
      },
    

    Make sure it is version 3 and not a higher version.

    Also if you are using any filenames that have spaces or numbers in them make sure to change the filename that gets uploaded in the resolver to something else or else the file may become corrupted.