Почему, когда я загружаю файл с помощью apollo-server, файл загружается, но файл имеет размер 0 КБ?

#file-upload #graphql #apollo #apollo-server #apollostack

#загрузка файла #graphql #apollo #apollo-server #apollostack

Вопрос:

Я пытался решить проблему, но я не понимаю, почему файл загружается, но его размер равен 0 КБ. Я вижу этот код в руководстве, но он работает над этим руководством, но у меня не работает

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

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

  type Query {
    hello: String!
  }

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

const resolvers = {
  Query: {
    hello: () => 'Hello world!',
  },
  Mutation: {
    fileUpload: async (_, { 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}`);
});
 

затем, когда я загружаю файл, он загружается, но файл имеет размер 0 КБ


вот так

Ответ №1:

Что происходит, так это то, что распознаватель возвращается до того, как файл был загружен, в результате чего сервер отвечает до того, как клиент завершил загрузку. Вам нужно пообещать и дождаться событий потока загрузки файла в распознавателе.

Вот пример:

https://github.com/jaydenseric/apollo-upload-examples/blob/c456f86b58ead10ea45137628f0a98951f63e239/api/server.js#L40-L41

В вашем случае:

 const resolvers = {
  Query: {
    hello: () => "Hello world!",
  },
  Mutation: {
    fileUpload: async (_, { file }) => {
      const { createReadStream, filename } = await file;
      const stream = createReadStream();
      const path = path.join(__dirname, `/public/images/${filename}`);

      // Store the file in the filesystem.
      await new Promise((resolve, reject) => {
        // Create a stream to which the upload will be written.
        const writeStream = createWriteStream(path);

        // When the upload is fully written, resolve the promise.
        writeStream.on("finish", resolve);

        // If there's an error writing the file, remove the partially written
        // file and reject the promise.
        writeStream.on("error", (error) => {
          unlink(path, () => {
            reject(error);
          });
        });

        // In Node.js <= v13, errors are not automatically propagated between
        // piped streams. If there is an error receiving the upload, destroy the
        // write stream with the corresponding error.
        stream.on("error", (error) => writeStream.destroy(error));

        // Pipe the upload into the write stream.
        stream.pipe(writeStream);
      });

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

Обратите внимание, что, вероятно, не стоит использовать такое имя файла для хранения загруженных файлов, поскольку будущие загрузки с тем же именем файла будут перезаписывать более ранние. Я не совсем уверен, что произойдет, если два файла с одинаковым именем будут загружены одновременно двумя клиентами.