`[File]` преобразуется в `[object File]`

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

Это мой код:

<script lang = "ts">
    let selectedFiles: File[] = [];
    function handleSubmit(e: any) {
        errorCode = validate(selectedFiles);
        if (errorCode) {
            console.info(errorCode);
            e.preventDefault();
        }
    }
    function handleFileSelect(e: any) {
        selectedFiles = [...selectedFiles, e.target.files[0]];
    }
    // Create ref to DOM element
    let fileInput: HTMLInputElement;
</script>

<form action = "?/submit" method = "post" on:submit = {handleSubmit}>
    <div>
        <label for = "files">Click "+" to add file</label>
        <button on:click = {(e) => {e.preventDefault(); fileInput.click();}}>
            <span>+</span>
        </button>
    <input type = "file" accept = {allowedExtensions} on:change = {handleFileSelect} on:invalid = {handleInvalid} bind:this = {fileInput} hidden/>
        <input type = "hidden" name = "contest" value = {contest.id} />
        <input type = "hidden" name = "user" value = {data.user.id} />
        <input type = "hidden" name = "files" value = {selectedFiles} />
        <p>Selected files: {getFileNames(selectedFiles).join(', ')}</p>
        <br />
        <button type = "submit" class = "btn btn-primary w-full">Submit</button>
    </div>
</form>

Я зарегистрировал request.formData(), и получилось вот так:

   [Symbol(state)]: [
     {
       name: 'files',
       value: '[object File],[object File],[object File]'
     },
     { name: 'contest', value: '5bvod8teq8kh7yn' },
     { name: 'user', value: 'dvkw0v6uz31zag2' },
     { name: 'score', value: '0' }
   ]

Я ожидал такого:

   [Symbol(state)]: [
     { name: 'files', value: [File] },
     { name: 'files', value: [File] },
     { name: 'files', value: [File] },
     { name: 'contest', value: '5bvod8teq8kh7yn' },
     { name: 'user', value: 'dvkw0v6uz31zag2' },
     { name: 'score', value: '0' }
   ]

Не уверен, что вы ожидаете, что свойство с именем files (множественное число от файла) будет иметь одно значение. Кроме того, объекты JavaScript не могут иметь несколько свойств с одним и тем же именем!

phuzi 16.04.2024 16:49

Когда я разрешил форме отправлять несколько файлов одновременно, request.formData — это именно то, что я ожидал. Однако мой клиент не принимает это решение

Alaire Sena 16.04.2024 16:58

Когда вы конвертируете объект в строку, значением по умолчанию является строка [object Prototypename]. Обычные объекты конвертируются в [object Object], файловые объекты конвертируются в [object File]. Когда вы вызываете .join() для массива объектов File, он преобразует их в строки и объединяет их.

Barmar 16.04.2024 17:11

Вы не можете загружать файлы с помощью type = "hidden", так как это текстовый ввод. Вам нужно использовать type = "file".

Barmar 16.04.2024 17:19

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

Alaire Sena 16.04.2024 17:32

Добавлен тег SvelteKit. Если он неверен, верните его.

brunnerh 16.04.2024 17:54
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
6
77
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Если вы создаете новые данные формы, вы можете добавить к ним файлы, хотя в этом случае запрос должен быть выполнен вручную/асинхронно. При использовании SvelteKit следует использовать действие Enhance, которое уже делает это и предоставляет доступ к данным формы в обратном вызове.

<script>
  function onSubmit({ formData }) {
    files.forEach(f => formData.append('files', f));
  }
</script>
<form
    method = "POST"
    use:enhance = {onSubmit}> ...

Также можно установить списки файлов на входах, что тоже можно сделать.

<script>
  let submittedFileInput;

  function onSubmit() {
    const transfer = new DataTransfer();
    files.forEach(f => transfer.items.add(f));
    submittedFileInput.files = transfer.files;
  }
</script>
...
<input bind:this = {submittedFileInput} style = "display: none"
       name = "files" type = "file" multiple />

РЕПЛ

Я попробовал первое предложение, но оно показало мне это Uncaught (in promise) TypeError: submit is not a function at HTMLFormElement.handle_submit. Итак, я следую этому и немного изменяю ваше предложение.

Alaire Sena 16.04.2024 18:46

Из первого предложения brunnerh я немного изменил его на основе настройки использования SvelteKit:улучшение:

<script lang = "ts">
    import { enhance } from '$app/forms';
    // rest of original code.

</script>

<form action = "?/submit" method = "post" on:submit = {handleSubmit} use:enhance = {({ formData }) => {
    selectedFiles.forEach(f => formData.append('files', f));
    return async ({result, update}) => {
        await applyAction(result);
        selectedFiles = [];
        update();
    }
}}>
    <!-- rest of original code -->
</form>

Спасибо большое, что указали на мою вину.

Другие вопросы по теме