How to send File uploads using fetch via Netlify forms?

One ugly way you might be able to solve this with JS and HTML is to create multiple forms, each with one file input, that look like they’re all one form.

I misspoke up ^^ there! You can currently have multiple file fields per form, but only one file per field. So I’m afraid the only way to currently upload multiple files in the same form is to have multiple file inputs. Not the same as the multiple keyword, but not as bad as my previous suggestion above- and possible with only JS and HTML.

Ok I found a way to do this using <input type="file" multiple>. You have to make manually (or generate using a templating language such as Pug like I did) a fixed amount of hidden single file inputs in HTML and then when you send the form, fill them in JS:

const file = document.getElementById('file'); // The <input type="file" multiple>
const hiddenInputs = document.getElementsByClassName('hidden-input');
document.getElementById('form').addEventListener('submit', event => {
    const files = file.files;
    if (files.length > hiddenInputs.length) {
        alert(`Can't send more than ${hiddenInputs.length} files.`);
        return event.preventDefault();
    }
    file.remove();
    for (let i = 0; i < files.length; ++i) {
        // Apparently you can't generate or modify a FileList but here's a workaround I found on StackOverflow:
        const transfer = new DataTransfer();
        transfer.items.add(files[i]);
        hiddenInputs[i].files = transfer.files;
    }
});

Make sure the hidden inputs have unique names, in my case numbers from 0 to 9.

Thanks for sharing this! People like you make Netlify Forums great :grinning: :netliheart:

4 Likes

I tried to do this but I am not sure I did this correctly. I have two file fields (they are clicks on a text link that evoke upload) but when I click the first and upload, then the second and upload, the second file is the only one that sticks.

Here is my code:


              <label for="full_name">Full name *</label>
              <Input type="text" name="full_name" id="full_name" required value={field} />

              <label for="email">Email address *</label>
              <Input type="text" name="email" id="email" required value={field} />

              <label for="phone">Phone</label>
              <Input type="text" name="phone" id="phone" value={field} />

              <label htmlFor="city">City</label>
              <Input type="text" name="city" id="city" value={field} />

              <label htmlFor="state">
                State
                <select name="state[]" size="1">
                  <option value="select">Please select your state</option>
                  <option value="AL">Alabama</option>
                  <option value="AK">Alaska</option>
                  <option value="AZ">Arizona</option>
                  <option value="AR">Arkansas</option>
                  <option value="CA">California</option>
                  <option value="CO">Colorado</option>
                  <option value="CT">Connecticut</option>
                  <option value="DE">Delaware</option>
                  <option value="DC">District Of Columbia</option>
                  <option value="FL">Florida</option>
                  <option value="GA">Georgia</option>
                  <option value="HI">Hawaii</option>
                  <option value="ID">Idaho</option>
                  <option value="IL">Illinois</option>
                  <option value="IN">Indiana</option>
                  <option value="IA">Iowa</option>
                  <option value="KS">Kansas</option>
                  <option value="KY">Kentucky</option>
                  <option value="LA">Louisiana</option>
                  <option value="ME">Maine</option>
                  <option value="MD">Maryland</option>
                  <option value="MA">Massachusetts</option>
                  <option value="MI">Michigan</option>
                  <option value="MN">Minnesota</option>
                  <option value="MS">Mississippi</option>
                  <option value="MO">Missouri</option>
                  <option value="MT">Montana</option>
                  <option value="NE">Nebraska</option>
                  <option value="NV">Nevada</option>
                  <option value="NH">New Hampshire</option>
                  <option value="NJ">New Jersey</option>
                  <option value="NM">New Mexico</option>
                  <option value="NY">New York</option>
                  <option value="NC">North Carolina</option>
                  <option value="ND">North Dakota</option>
                  <option value="OH">Ohio</option>
                  <option value="OK">Oklahoma</option>
                  <option value="OR">Oregon</option>
                  <option value="PA">Pennsylvania</option>
                  <option value="RI">Rhode Island</option>
                  <option value="SC">South Carolina</option>
                  <option value="SD">South Dakota</option>
                  <option value="TN">Tennessee</option>
                  <option value="TX">Texas</option>
                  <option value="UT">Utah</option>
                  <option value="VT">Vermont</option>
                  <option value="VA">Virginia</option>
                  <option value="WA">Washington</option>
                  <option value="WV">West Virginia</option>
                  <option value="WI">Wisconsin</option>
                  <option value="WY">Wyoming</option>
                </select>
              </label>
              <p></p>
              <label for="linkedin">LinkedIn Profile URL</label>
              <Input type="text" name="linkedin" id="linkedin" value={field} />

              <label for="hear_from">How did you hear about this job? *</label>
              <Input type="text" name="hear_from" id="hear_from" required value={field} />

              <Attach for="attachment">Attach Resume *</Attach>
              <input
                hidden
                id="attachment"
                type="file"
                name="attachment"
                value={field}
                onChange={(e) => {
                  setFileName(e.target.files[0].name);
                }}
              />
              <p></p>
              <Attach for="attachment">Attach Cover Letter</Attach>
              <input type="file" id="file2" name="file2" />
              {filename && message !== 'Email sent successfully!' && (
                <Text kind="p">{filename}</Text>
              )}
              <Button type="submit" center>
                Send
              </Button>

              {message && (
                <Text center padded kind="p">
                  {message}
                </Text>
              )}
            </form>
          </Form>

Sounds like it could be an issue with how you’re handling form inputs, since it does work to have two different file fields that each accept one file. Could you please take a look at the POST request body in your browser dev tools and let us know if it includes the first file?