I have set up a mutation on my apollo
GraphQL server with graphql-upload
(or apollo-upload-server
) to receive a file from the client, and now I'm trying to write a test for this mutation but I'm not sure how to attach the actual file to my mock request.
On my client I have an input type="file"
and on upload event I extract the file
async upload(event) {
const files = event.target.files || event.dataTransfer.files;
const file = files[0]; // type of file is File
await apollo.mutate({
mutation: gql`
mutation UploadFile($file: Upload) {
uploadFile(file: $file)
}
`,
variables: { file },
})
}
So far all is good. But I would like to write a test case on my server as well.
This is my problem
On my server, I would like to mimic the client uploading the file. But I can't find how I'd access the actual file from within NodeJS.
I've tried:
const file = fs.readFileSync('path/to/test-file.csv');
But fs
returns a Buffer
, not of type File
which also contains meta-data, such as mimetype
, name
, lastModified
properties for instance.
How do I get the actual File
object and not the Buffer
?
Thanks!
There is no File
class in Node.js. There is not even, as of writing this, any other class that would, say, encapsulate accessing the MIME type, contents, and name of a file. You will have to use "lower level" methods to accomplish what you want:
fs.readFileSync
that gets you the file's contents from a file descriptor or file path.fs.lstatSync
and fs.fstatSync
that [synchroniously, like with readFileSync
] get you some of the attributes you want, in particular the "last modified timestamp" of the file.There is no definite accepted way to obtain a file's MIME type -- even though some MIME types for some kinds of data are standardized, heuristical analysis of the contents is typically applied to determine the MIME type of a file. For instance, for an SVG file (typically *.svg
) which is also a valid XML file, you'd want to make sure the file is parseable as XML in so far as to determine that the root "svg" element belongs to the SVG namespace by comparing the declared namespace URI to the known SVG element namespace, before positively asserting that the file is of the image/svg+xml
MIME type. This kind of approach -- some analysis of actual file contents -- would apply to any case of determining a MIME type, if one wants to be certain.
Now, most Web servers just use the file's extension as a key to a MIME type map -- for instance, all *.gif
files are said to be of image/gif
MIME type, even if there is garbage or plain text in them. That's because neither the Web server nor the client typically needs heuristical analysis -- if the file that is assumed to be a GIF is actually garbage, the client will abort rendering or render garbage, but the responsibility to ensure the file contents are valid, lies on whoever owns the file, not the Web server, and the latter does not care much for the contents anyway, it only serves content, parsing it isn't really its responsibility normally (not for "asset" files). The real reason, however, is performance, of course -- given how heuristical analysis is more often than not more costly than just deciding the MIME type based on file extension, the latter method is preferred.