keystone
keystone copied to clipboard
Image uploading through the backend db api fails
Hello, Guys!
I've tried to upload an image via backend api, but not luck. So, I have local image, getting it as stream, then creating Upload instance. I've used the following code:
const upload = prepareToUpload(__dirname + '/tmp.jpg');
const image = await localDb.Image.createOne({
data: {
image: {
upload: upload,
}
}
});
const prepareToUpload = (filePath: string) => {
const filename = path.basename(filePath);
const stream = fs.createReadStream(filePath);
const createReadStream = () => stream;
const mimetype = 'image/jpeg';
const encoding = 'utf-8';
const image: Upload = {
createReadStream,
filename,
mimetype,
encoding,
};
const upload = new Upload();
upload.resolve(image);
return upload;
};
Expected to be Image uploaded but got this error:
Error creating Image GraphQLError: Variable "$data" got invalid value { resolve: [function], reject: [function], promise: {}, file: { createReadStream: [function createReadStream], filename: "tmp.jpg", mimetype: "image/jpeg", encoding: "utf-8" } } at "data.image.upload"; Upload value invalid.
node 16.20.0
"@keystone-6/auth": "^7.0.0",
"@keystone-6/core": "^5.2.0",
"@keystone-6/fields-document": "^8.0.0",
"dotenv": "^16.0.3",
"graphql-upload": "^16.0.2",
"nodejs-mysql": "^0.1.3",
"readable": "^1.1.3",
"request": "^2.88.2"
Hi,
This error most probably means that the Upload instance you created is invalid and graphql-upload fails it's check.
I am not an expert in graphql-upload, but have a look at code that works for me (https://github.com/keystonejs/keystone/issues/7986#issuecomment-1459606289). Comparing those, I think you need to promisify your image
before upload.resolve
. Just guessing, did not try it.
Hello, @marekryb Thank you, yes I've checked its type and it was Upload. Anyway, tried your way for convert it into Upload again, but no luck.
But, it is strange issue on my and that I was unable to import Upload standard way, so I've used it like the following.
const uploadImport = await import('graphql-upload/Upload.mjs');
const upload = new uploadImport.default;
@molotow11 I checked your code and it works fine (except for types).
Now that you mentioned that you import Upload.mjs
, I think I know what is happening.
keystone is using graphql-upload 15.0.2 https://github.com/keystonejs/keystone/blob/a412558e5e44abcba4e675da9a0d3e486231148d/packages/core/package.json#L252 and you are probably using 16.0.2.
This can create all kind of weird things, including mismatch of class prototypes. Try installing exact version that keystone is using.
Also now looking at your error message, you can see that your Upload object has empty promise (promise {}
), but this is what is used later in graphql-upload
if (value instanceof Upload) return value.promise;
@marekryb
Thanks so much, yes it works fine with "graphql-upload": "^15.0.2",
But, is it stable solution?
It depends how you define stable.
Just whenever you update keystone, you need to keep track of graphql-upload
version changes.