How do you upload a file to Keystone? #54
Replies: 5 comments 4 replies
-
On the server Note: For seeding the database consider doing this outside of Keystone with something like Knex or Mongoose. The short answer is that for seeding or migration at this point in time you're probably best initialising this data outside of Keystone with either Mongoose, Knex or whatever your favourite tool is. If you really do need to use a Node script to upload a file you can hit the graphQL end point directly and here is an example provided by @jesstelford again. const FormData = require('form-data');
const fetch = require('node-fetch');
const request = require('request');
const graphqlUri = 'http://localhost:60000/admin/api';
const avatarUrl = 'https://en.gravatar.com/userimage/18405287/42d1f0e4b3ec1cdefe5bd89a571bab49.jpg?size=600';
const body = new FormData();
body.append(
'operations',
JSON.stringify({
query: /* GraphQL */ `
mutation createUser($data: UsersCreateInput) {
createUser(data: $data) {
name
avatar {
publicUrl
}
}
}
`,
variables: {
data: {
name: "Jess Telford",
avatar: null,
},
},
})
);
body.append('map', { 0: [`variables.data.avatar`] });
body.append('0', request(avatarUrl))
fetch(graphqlUri, {
method: 'POST',
body,
}); As you can see you will need to hit the graphQL endpoint directly. Checkout the Form Data library: https://www.npmjs.com/package/form-data for different methods of submitting multi-part forms including with local files or buffers. |
Beta Was this translation helpful? Give feedback.
-
In the front-end: The file adapters implement the Apollo Server Upload type: https://www.apollographql.com/docs/apollo-server/data/file-uploads/, this means the client needs to submit the value of the field as a DOM File instance. const graphqlUri = 'http://localhost:60000/admin/api';
const image = document.getElementById("file-input").files[0];
const formData = new FormData();
formData.append("avatar", image);
formData.append('operations',
JSON.stringify({
query: /* GraphQL */ `
mutation createUser($data: UsersCreateInput) {
createUser(data: $data) {
name
avatar {
publicUrl
}
}
}
`,
variables: {
data: {
name: "Jess Telford",
avatar: null,
},
},
})
)
fetch(graphqlUri, {method: "POST", body: formData}); |
Beta Was this translation helpful? Give feedback.
-
Figured ouat a way to upload/seed file types when working server side. const filename = 'user.jpg';
const file = `/path/to/file/${filename}`;
const mimetype = mime.getType(file); // yarn add mime // installed already with keystonejs
const createReadStream = () => fs.createReadStream(file);
const encoding = 'utf-8'
const image = { createReadStream, filename, mimetype, encoding }; you can now use this await keystone.executeGraphQL({
context: keystone.createContext({ skipAccessControl: true }),
query: `
mutation createUser($data: UserCreateInput) {
createUser(data: $data) { id name avatar { publicUrl } }
}
`,
variables: {
data: {
name,
email,
avatar: image,
},
},
}); const { createItem } = require('@keystonejs/server-side-graphql-client');
await createItem({
keystone,
listKey: 'User',
item: {
name,
email,
avatar: image,
},
returnFields: 'name, avatar { publicUrl }'
}); |
Beta Was this translation helpful? Give feedback.
-
I had no luck with the
method. I tried all sorts of combinations of variables, but it keeps complaining
I had the same idea as you to mimic the Upload file format, but I haven't been able to nail down what it is. https://www.apollographql.com/blog/file-uploads-with-apollo-server-2-0-5db2f3f60675/ What worked though was a version of @jesstelford method above, with some minor changes:
|
Beta Was this translation helpful? Give feedback.
-
Building on the solution by @gautamsi using
|
Beta Was this translation helpful? Give feedback.
-
It turns out uploading a file from node via GraphQL is not as straight forward as it seems. Or as easy as it could potentially be.
The
keystone.createItems()
method was only intended for basic scalar types and is really only a stop-gap measure for getting some data into keystone is certain circumstances. It's not a full migration or seeding solution. For that see the ongoing discussion here: https://github.com/keystonejs/keystone/discussions/299The next method you might try is
keystone.executeQuery()
you can do more with this but files are still "special". This is mostly because as @jesstelford explains here: keystonejs/keystone#1943, "it needs to be submitted as a multipart form, not json type" andkeystone.executeQuery()
does not now, and probably won't in the near future add special support for file types.So, how do we upload a file in Node?
Beta Was this translation helpful? Give feedback.
All reactions