Graphql Server Express file upload middleware. Used together with apollo-upload-network-interface.
graphqlExpressUpload
middleware to your Express GraphQL endpointimport { graphqlExpress, graphiqlExpress } from 'graphql-server-express'
import bodyParser from 'body-parser'
import graphqlExpressUpload from 'graphql-server-express-upload'
import multer from 'multer'
import schema from './schema'
const upload = multer({
dest: config.tmp.path,
})
app.use('/graphql',
upload.array('files'),
bodyParser.json(),
graphqlExpressUpload({ endpointURL: '/graphql' }), // after multer and before graphqlExpress
graphqlExpress((req) => {
return {
schema,
context: {}
}
})
)
app.use('/graphiql', graphiqlExpress({
endpointURL: '/graphql',
}))
UploadedFile
scalar to your schemascalar UploadedFile
UploadedFile
resolverFor now we simply use JSON. In the future we should improve this.
const resolvers = {
UploadedFile: {
__parseLiteral: parseJSONLiteral,
__serialize: value => value,
__parseValue: value => value,
}
...
}
function parseJSONLiteral(ast) {
switch (ast.kind) {
case Kind.STRING:
case Kind.BOOLEAN:
return ast.value;
case Kind.INT:
case Kind.FLOAT:
return parseFloat(ast.value);
case Kind.OBJECT: {
const value = Object.create(null);
ast.fields.forEach(field => {
value[field.name.value] = parseJSONLiteral(field.value);
});
return value;
}
case Kind.LIST:
return ast.values.map(parseJSONLiteral);
default:
return null;
}
}
Schema definition
uploadProfilePicture(id: Int!, files: [UploadedFile!]!): ProfilePicture
And the mutation function
async uploadProfilePicture(root, { id, files }, context) {
// you can now access files parameter from variables
console.log('uploadProfilePicture', { id, files })
//...
}
Example using react-apollo
. Don't forget that you need to be using UploadNetworkInterface, because apollo-client
does not support multipart/form-data
out of the box.
import React, { Component, PropTypes } from 'react'
import { graphql } from 'react-apollo'
import gql from 'graphql-tag'
class UploadProfilePicture extends Component {
onSubmit = (fields) => {
const { user, uploadProfilePicture } = this.props
// fields.files is an instance of FileList
uploadProfilePicture(user.id, fields.files)
.then(({ data }) => {
console.log('data', data);
})
.catch(error => {
console.log('error', error.message);
})
}
render() {
return (
//...
)
}
}
const UPLOAD_PROFILE_PICTURE = gql`
mutation uploadProfilePicture($id: Int!, $files: [UploadedFile!]!) {
uploadProfilePicture(id: $id, files: $files) {
id url thumb square small medium large full
}
}`
const withFileUpload = graphql(UPLOAD_PROFILE_PICTURE, {
props: ({ ownProps, mutate }) => ({
uploadProfilePicture: (id, files) => mutate({
variables: { id, files },
}),
}),
})
export default withFileUpload(UploadProfilePicture)