1

Apollo Server 2.0 has the ability to receive file uploads as described in this blog post.

However, all the tutorials and blog posts I found only showed how to upload a file. Nobody demonstrated how to actually retrieve the file back to display it onscreen.

Does anybody know how to properly query the file contents for display onscreen?
Also, there's the possibility that maybe there is no way of querying a file and you have to build a separate rest endpoint to retrieve the contents?

Some thoughts:
I imagine the query to be something like

query {
  fetchImage(id: 'someid')
}

with the respective server-side definition

type Query {
  fetchImage(id : ID!): Upload //maybe also a custom type, but how do I include the actual file contents?
}

Hint: Upload is a scalar type that apollo-server automatically adds to your type definition. It is used for the upload so I imaging it also being usable for the download/query. Please read the blog post mentioned above for more information.

Rockettomatoo
  • 257
  • 6
  • 18

2 Answers2

0

The response from a GraphQL service is always serialized as a JSON object. Technically, a format other than JSON could be used in serialization but in practice only JSON is used because it meets the serialization requirements in the spec. So, the only way to send a file through GraphQL would be to convert the file into some format that's JSON-compatible. For example, you could convert a Buffer to a byte array and send that as an array of integers. You would also have to send the appropriate mime type. It would be up to the client to convert the byte array back into a usable format on receiving the response.

If you go this route, you'd have to use your own scalar or object type -- the Upload scalar does not support serialization so it will throw if you try to use it as an output type (and it's not really suitable for this sort of thing anyway).

However, while doing this is technically possible, it's also inadvisable. Serializing a larger file could cause you to run out of memory since there's no way to stream data through GraphQL (the entire response has to be in memory before it can be sent). It's much better to serve the file statically (ideally using nginx instead of Node). If your API needs to refer to the file, it can then just return the file's path.

Daniel Rearden
  • 80,636
  • 11
  • 185
  • 183
  • since apollo implemented a multipart/form-data upload mechanism (that isn't serializing the file) do you know anything about implementing something similar to also retrieve the file? Or is that what you meant by technically possible but inadvisable? – Rockettomatoo Aug 30 '19 at 12:33
  • I'm very sorry for the stupid question but why implement an upload functionality in the first place when the opposite equivalent (download/query functionality) is not advisable and thus should be done separately? – Rockettomatoo Aug 30 '19 at 13:22
  • To be clear -- it's inadvisable for much the same reason you wouldn't use Express to serve files statically (i.e. response time and memory usage). Upload functionality exists because there's a clear use case for wanting to provide both the file and some related data inside the same request. If you're already exposing a GraphQL endpoint, it can be a hassle to implement a separate endpoint or endpoints for uploads, particularly if you want to include validation, documentation, etc. for those endpoints. – Daniel Rearden Aug 30 '19 at 13:49
  • Wanting to fetch information about a resource and simultaneously download some associated files just isn't a very common use case. Having an API return urls to the files is much more suitable for most cases. You wouldn't want to request a profile and have the browser suddenly start downloading the profile photo, for example. – Daniel Rearden Aug 30 '19 at 13:51
  • Thank you very much for the explanation. (I'm using MongoDB + GridFS for my file handling thus I kind of have to go through apollo/express to serve my files ... I have a relatively small app and thus I don't need to have the absolute best performance - thats why I asked :)) – Rockettomatoo Aug 30 '19 at 13:58
-1

You can do this by installing express with apollo server.

apollo-server-express

Install above package and instantiate Express object with Apollo Server as explained in package docs.

Then set the static folder using express like this

app.use("/uploads", express.static("uploads")); //Server Static files over Http

uploads is my static folder & /uploads will server get request to that path

//Now I can access static files like this
http://localhost:4000/uploads/test.jpg
pranav shinde
  • 1,260
  • 13
  • 11