How do I upload files to a graphql backend impleme

2020-07-25 01:02发布

问题:

I have a GraphQL backend implemented using express, express-graphql, graphql and graphql-upload. My GraphQL schema declaration is as follows:

type OProject {
    _id: ID!
    title: String!
    theme: String!
    budget: Float!
    documentation: String!
    date: Date
}

input IProject {
    title: String!
    theme: String!
    budget: Float!
    file: Upload!
}

type Mutations {
    create(data: IProject): OProject
}

type Mutation {
    Project: Mutations
}

I want to make a create request to my GraphQL API at /graphql using axios. How go I go about it?

回答1:

Following the GraphQL multipart request specification detailed here you would go about doing so by:

  • creating a FormData instance and populating it with the following:
    • The operations field,
    • the map field and,
    • the files to upload

Creating the FormData Instance

var formData = new FormData();

The operations field:

The value of this field will be a JSON string containing the GraphQL query and variables. You must set all file field in the variables object to null e.g:

const query = `
    mutation($project: IProject!) {
        Project { create(data: $project) { _id } }
    }
`;

const project = {
    title: document.getElementById("project-title").value,
    theme: document.getElementById("project-theme").value,
    budget: Number(document.getElementById("project-budget").value),
    file: null
};

const operations = JSON.stringify({ query, variables: { project } });
formData.append("operations", operations);

The map field:

As its name implies, the value of this field will be a JSON string of an object whose keys are the names of the field in the FormData instance containing the files. The value of each field will be an array containing a string indicating to which field in the variables object the file, corresponding to value's key, will be bound to e.g:

const map = {
    "0": ["variables.project.file"]
};
formData.append("map", JSON.stringify(map));

The files to upload You then should add the files to the FormData instance as per the map. In this case;

const file = document.getElementById("file").files[0];
formData.append("0", file);

And that is it. You are now ready to make the request to your backend using axios and the FormData instance:

axios({
    url: "/graphql",
    method: "post",
    data: formData
})
    .then(response => { ... })
    .catch(error => { ... });