Как загрузить несколько файлов с дополнительной информацией внутри объекта

#javascript #file-upload #axios #form-data

Вопрос:

Я пытаюсь загрузить несколько файлов, используя FormData в качестве массива объекты, содержащие файл и другие необходимые свойства, но я не получаю ожидаемых результатов.

 import api from './api';

const formData = new FormData();

// File input with multiple attribute
const files = this.$refs.photo.files;

if (files.length > 0) {
  for (let i = 0; i < files.length; i  ) {
    formData.append('files', { file: files[i], someOtherProp: 'value' });
  }
}

api.createArticle(formData);
 
 // api/index.js

import axios from 'axios';
import config from '@/config';

const api = axios.create({
  baseURL: config.api,
  timeout: config.apiTimeout,
});

createArticle(payload) {
  return api.post('/articles', payload, {
    headers: {
      'Content-Type': 'multipart/form-data',
    }
  });
}

export {
  createArticle
};

 

Когда я отправляю запрос, это то, что я получаю

введите описание изображения здесь

Комментарии:

1. Вы не должны добавлять объекты, только строки или файлы. Добавьте файлы и дополнительную информацию отдельно. Смотрите здесь: developer.mozilla.org/en-US/docs/Web/API/FormData/append

2. Сервер @ADyson видит файлы как массив, когда я отправляю только файл без других реквизитов, используя files синтаксис. — formData.append('files', files[i]);

Ответ №1:

Документация функции добавления FormData показывает, что она принимает два или три параметра (3-й является необязательным).

О втором параметре — value — в нем говорится:

Значение поля. Это может быть строка USV или большой двоичный объект (включая подклассы, такие как файл). Если ни один из них не указан, значение преобразуется в строку.

Ваш код пытается передать объект для этого параметра, а не строку или большой двоичный объект. Поэтому FormData делает именно то, что указано в документации, и преобразует этот объект в строку. [Object object] это то, что JavaScript всегда выводит по умолчанию, если вы пытаетесь напрямую структурировать объект.

Если вы хотите добавить имя файла специально, как вы можете видеть из документации, дополнительный 3-й параметр filename предоставляется специально для этой цели.

Однако, если вы хотите передать какое-либо другое связанное свойство, вам нужно будет сделать это в отдельном поле в FormData.

Также не следует повторно добавлять элементы данных с одним и тем же именем — ваш сервер может видеть только последний. Чтобы это работало наиболее надежным способом , вы должны использовать синтаксис массива, например formData.append("files[]"... , чтобы сервер видел массив данных с этим именем, а не один элемент. Вы можете сделать то же самое для этих дополнительных свойств, которые вы хотите передать, затем вы также можете передать несколько элементов, и их номер индекса будет совпадать с номером индекса файла, с которым они связаны, когда ваш сервер получит опубликованные данные.

Например, что-то вроде этого должно работать лучше:

 for (let i = 0; i < files.length; i  ) {
  formData.append('files[]', files[i]);
  formData.append('someOtherProp[]', 'value');
}
 

Комментарии:

1. Я знаю, что могу отправить другую опору в качестве отдельной опоры, но это не то, чего я собираюсь достичь. Например, если я загружаю несколько изображений, я хочу выбрать некоторые из этих изображений и сказать, что это изображение является основным.

2. Ну, вам нужно придумать какой — то способ представления этого факта серверу, но вы должны сделать это с помощью отдельного свойства — например, возможно, вы можете .append("mainImage", "filenameOfMainImage") .append("mainImageIndex", 0) или что-то в этом роде-просто некоторая информация, чтобы сообщить серверу, какое из изображений в массиве является «основным». Используй свое воображение.

3. Тем не менее, я ответил на конкретный вопрос о том, почему вы получаете результат, который вы видели, — это потому, что то, что вы предоставили .append() методу, не поддерживается. Для свойства необходимо указать только строку или большой двоичный value объект. Я также объяснил возможный альтернативный подход, который поддерживается, и дал вам идеи для других альтернативных подходов, а также для вашего конкретного случая использования. Поэтому я думаю, что вопрос более чем решен. Точная структура данных, которую вы выберете, действительно зависит от вас, но я объяснил, что вам разрешено, а что нет.

4. Спасибо, я отправлю файлы отдельно от других реквизитов.