AxeWP/wp-graphql-gravity-forms

Single file upload FAILED (Temporary file could not be copied.)

marcinkrzeminski opened this issue · 6 comments

Description

Hi,

I'm having a problem with a single file upload. The form submission works fine and I actually get a success message but when I check a single entry the file field shows FAILED (Temporary file could not be copied.).

Steps to reproduce

The file upload field looks like this

id,
fileUploadValues: [
  {
    name: value[0].name,
    type: value[0].type,
    size: value[0].size
  }
]

I'm not passing a tmp_name since it's resolved on the plugin level.

if (empty($value['tmp_name'])) {
  $tmp_dir = get_temp_dir();
  $value['tmp_name'] = $tmp_dir . wp_unique_filename($tmp_dir, $value['name']);
}

I have tried to use the default tmp path which is /var/tmp/ on macOS with Laravel Valet, as well as setting the path via WP_TEMP_DIR and setting it to the /Users/marcin/Sites/REDACTED/REDACTED/wp-content/uploads/gravity_forms/tmp/.

Additional context

No response

Plugin Version

0.12.0

Gravity Forms Version

2.7.3

WordPress Version

6.1.1

WPGraphQL Version

1.14.00

Additional enviornmental details

No response

Please confirm that you have searched existing issues in the repo.

  • Yes

Please confirm that you have disabled ALL plugins except for Gravity Forms, WPGraphQL, and WPGraphQL for Gravity Forms

  • Yes
  • My issue is with a specific 3rd-party plugin.

Hey @marcinkrzeminski it seems your manually creating an object instead of using the Upload type (which on your front end would be the actual File object i.e. value). Please see this example for more info.

Hey @justlevine. Thanks for your response.

When I use value I'm getting this error Expected type Upload at value.fieldValues[5].fileUploadValues[0]; Could not get uploaded file, be sure to conform to GraphQL multipart request specification. Instead got: []

When I replace it with value[0] the form is submitted but the file is not present on the entry.

Any suggestions what could be wrong here?

@justlevine also, not sure if this is important but I'm sending the query using fetch like this

fetch(process.env.WORDPRESS_API_URL, {
  headers: {
    "Content-Type": "application/json"
  },
  method: "POST",
  body: JSON.stringify({
    query,
    variables
  })
})...

I have tried multipart/form-data for Content-Type as well.

P.S. Do I have to register_graphql_mutation as per: https://github.com/dre1080/wp-graphql-upload#usage?

For the ones looking for a solution.

I ended up usig Apollo Client with the apollo-upload-client

import { ApolloClient, gql, InMemoryCache, useMutation } from '@apollo/client';
import { createUploadLink } from 'apollo-upload-client';

function Submit() {
  const client = new ApolloClient({
    cache: new InMemoryCache(),
    link: createUploadLink({
      uri: process.env.WORDPRESS_API_URL
    })
  });

  const SUBMIT_MUTATION = gql`
    mutation ($input: SubmitGfFormInput!) {
      submitGfForm(input: $input) {
        confirmation {
          type
          message
          url
        }
        errors {
          id
          message
        }
      }
    }
  `;

  const [formSubmitMutation] = useMutation(SUBMIT_MUTATION, { client });

  const onSubmit = (event) => {
    event.preventDefault();
    const variables = {
      input: {
        id: formId,
        fieldValues: getFieldsValues()
      }
    };

    formSubmitMutation({ variables }).then((response) => {
      console.log(response);
    });
  };


 return (<><form onSubmit={onSubmit}>....</form></>);

}

Make sure to create getFieldsValues() and return the values you actually need. For the files it needs be an object that looks like this:

{
id: FIELD_ID,
fileUploadValues: [{INPUT_FILE_VALUE}]
}

@marcinkrzeminski, do you think you could post what your getFieldsValues() looks like? Also, are you using Formik or anything like that to create the form? I've been battling this for the past 3 days and can't seem to get this to work.

@RaymondMRose it's a helper function that maps to the format that the plugin requires. No Formik, nor any other form library. It was a simple form, we handled that ourselves.

export const getFieldsValues = (formState, gReCaptchaToken = null) => {
  return Object.keys(formState).map((field) => {
    const { value, type } = formState[field];
    const id = parseInt(field, 10);

    switch (type) {
      case 'EMAIL':
        return {
          id,
          emailValues: {
            value,
            confirmationValue: value
          }
        };
      case 'CHECKBOX':
        return {
          id,
          checkboxValues: value
        };
      case 'RADIO':
        return {
          id,
          value: value || ''
        };
      case 'FILEUPLOAD':
        return {
          id,
          fileUploadValues: value
        };
      case 'HIDDEN':
        return {
          id,
          value
        };
      case 'HTML':
        return;
      default:
        return {
          id,
          value
        };
    }
  });
};