Я пишу форму выбора файла, в которой каждый раз, когда выбирается файл, этот файл добавляется в существующий массив файлов. Я намерен отправить этот массив через форму, но после отправки массив преобразуется в строку. Я не знаю, как с этим справиться, пожалуйста, помогите мне.
Это мой код:
<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' }
]
Когда я разрешил форме отправлять несколько файлов одновременно, request.formData — это именно то, что я ожидал. Однако мой клиент не принимает это решение
Когда вы конвертируете объект в строку, значением по умолчанию является строка [object Prototypename]. Обычные объекты конвертируются в [object Object], файловые объекты конвертируются в [object File]. Когда вы вызываете .join() для массива объектов File, он преобразует их в строки и объединяет их.
Вы не можете загружать файлы с помощью type = "hidden", так как это текстовый ввод. Вам нужно использовать type = "file".
Судя по этому ответу, похоже, я не могу назначить файл для ввода, как вы предлагаете. Я думал о манипулировании данными этой формы, но похоже, что такое поведение тоже запрещено.
Добавлен тег SvelteKit. Если он неверен, верните его.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Если вы создаете новые данные формы, вы можете добавить к ним файлы, хотя в этом случае запрос должен быть выполнен вручную/асинхронно. При использовании 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. Итак, я следую этому и немного изменяю ваше предложение.
Из первого предложения 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>
Спасибо большое, что указали на мою вину.
Не уверен, что вы ожидаете, что свойство с именем
files(множественное число от файла) будет иметь одно значение. Кроме того, объекты JavaScript не могут иметь несколько свойств с одним и тем же именем!