Я использую Vuejs для создания формы загрузки.
Проблема в том, что когда я загружаю ключ объекта, внутренний сервер получает пустой запрос:
лайк axios.postForm(app_url() + 'api/upload', { files: e.target.files[key] }, api_config())
Но когда я загружаю следующее выражение (все файлы вместе), оно работает правильно:
лайк axios.postForm(app_url() + 'api/upload', { files: e.target.files }, api_config())
В чем причина этой проблемы? и как я могу отправлять файлы на сервер отдельно и одновременно?
Вот код:
<script setup>
import uploadIcon from '../assets/images/direct-inbox.png';
import axios from 'axios';
import app_url from '../customJavascript/app_url';
import api_config from '../customJavascript/api_config';
const changeFile = (e) => {
const all = [];
for (const key in e.target.files) {
if (typeof e.target.files[key] == 'object') {
all.push(axios.postForm(app_url() + 'api/upload', { files: e.target.files }, api_config()));
}
}
axios.all(all)
.then(axios.spread((data1, data2) => {
console.info('data1', data1, 'data2', data2)
}));
}
</script>
<template>
<div class = "main-card">
<p class = "main-card-title">upload file</p>
<div class = "mt-6 flex justify-center">
<div class = "upload-card clickable focus:shadow-none">
<div class = "relative text-center h-full flex flex-col justify-center align-center">
<input type = "file" @change = "changeFile"
class = "rounded-2xl cursor-pointer absolute right-0 top-0 w-full h-full opacity-0" multiple />
</div>
</div>
</div>
</div>
</template>
<style>
.upload-card {
@apply w-11/12 lg:w-5/12 h-60 lg:h-60 rounded-2xl border-2 border-lightblue bg-white hover:shadow-lg;
}
.upload-card:hover button {
@apply bg-primary;
}
</style>
Я поместил код вне цикла и отправил запрос только со статической переменной index. Я ожидал, что, возможно, цикл вызвал эту проблему, но это не так.
Серверная часть в порядке, это PHP Laravel



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


похоже, ваш сервер ожидает массив файлов.
если вы хотите загружать файлы отдельными запросами, вам необходимо иметь это: { files: [e.target.files[key]] }
PS: вы также можете использовать функции фильтра + карты:
const all = e.target.files
.filter((file) => typeof file === 'object')
.map((file) => axios.postForm(app_url() + 'api/upload', { files: [file] }, api_config());
На самом деле я превратил объект файлов в массив, и с помощью цикла for of это сработало.
в вашем коде вы используете for in, а не for of
В вашем коде e.target.files — это объект FileList [w3c] . Этот интерфейс представляет собой список объектов File [w3c].
Итерация не делает того, что вы думаете.
for (const key in e.target.files) // [for ••• in [mdn] statement]Он перебирает указанную переменную по всем перечислимым свойствам FileList. См. пример [mdn].
Чтобы правильно перебрать значения FileList, используйте:
for (const file of e.target.files) // [for ••• of [mdn] statement]Теперь он перебирает последовательность значений, полученных из объекта FileList.
И наконец, верен ли этот тест? [1]
if (typeof e.target.files[key] == 'object')Технически, вы перебираете перечислимые свойства FileList и проверяете, является ли каждое свойство object.
Мне придется остановиться здесь. [2]
Чтобы загрузить данные по HTTP, тип данных должен быть правильно указан, чтобы сообщить серверу, как обрабатывать входящие данные. Это вы укажете в шапке вашего запроса. Заголовок Content-Type часто используется со значением multipart/form-data. Большинство серверов знают, что делать, когда получают это.
К счастью, axios справится со стрессом, когда вы используете axios.postForm().
[1] I had a feeling this will be asked.
[2] I stopped there because I couldn’t justify to myself why the code after the if statement is even there.
Это полностью зависит от бэкэнда. Ваша конечная точка
/upload, скорее всего, ожидает запрос, содержащий определенную полезную нагрузку, например. массив файлов или FileList, а не один файл.