Отправка файла с помощью Formdata в React на сервер Express на NodeJS
На странице имеется форма и кнопка для отправки файла (используется React):
const Upload = () => {
const [file, setFile] = useState();
const UploadContent = (event) => {
event.preventDefault();
if (event.target.files[0]) {
setFile(event.target.files[0]);
}
};
const OnSumbit = (event) => {
const formData = new FormData();
formData.append('customFile', file);
axios.post(
"http://localhost:3000/upload",
formData,
{
headers: {
"Content-type": "multipart/form-data"
},
}
)
.then(res => {
console.log(`Success` + res.data);
})
.catch(err => {
console.log(err);
})
}
return <div>
<h1 style={style}>Зона тестов</h1>
<input
accept="video/mp4"
id="contained-button-content"
multiple
type="file"
onChange={UploadContent}
/>
<Button variant="contained" color="primary" onClick={OnSumbit}>
Сохранить и закрыть
</Button>
</div>
}
На сервере используется files-uploader:
app.post('/upload', function(req, res) {
let sampleFile;
let uploadPath;
if (!req.file || Object.keys(req.file).length === 0) {
return res.status(400).send('No files were uploaded.');
}
sampleFile = req.file.customFile;
uploadPath = __dirname + '/uploads/' + sampleFile.name;
customFile.mv(uploadPath, function(err) {
if (err)
return res.status(500).send(err);
res.send('File uploaded!');
});
});
Не могу разобраться в чём дело, почему не загружается файл. Буду благодарен за любую помощь.
Ответы (2 шт):
Вместо того чтобы пытаться сохранить файл в стейт, лучше вставить input в форму и из неё уже создавать FormData:
const Upload = () => {
const OnSumbit = (event) => {
event.preventDefault();
const formData = new FormData(event.target.form);
axios
.post("http://localhost:3000/upload", formData, {
headers: {
"Content-type": "multipart/form-data",
},
})
.then((res) => {
console.log(`Success` + res.data);
})
.catch((err) => {
console.log(err);
});
};
return (
<form onSubmit={OnSumbit}>
<h1 style={style}>Зона тестов</h1>
<input
accept="video/mp4"
id="contained-button-content"
name="customFile"
type="file"
/>
<Button variant="contained" color="primary">
Сохранить и закрыть
</Button>
</form>
);
};
Я убрал из файла атрибут multiple, поскольку в оригинальном коде всё равно попытки отправить один фапйл, но можно вернуть обратно - от этого работать клиентская часть не перестанет.
Я так же убрал onClick у кнопки. Если это настоящая кнопка, то она запустит процесс отправки формы по-умолчанию.
Проблема была в элементарном отсутствии папок для сохранения файлов.
Для загрузки файлов использовался multer и сам скрипт модуль загрузки выглядит так:
const path = require('path');
const multer = require('multer');
const fs = require('fs');
const filePath = {
common : './content/',
imageFile: './uploads/images/',
contentFile: './uploads/content/'
}
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, path.join(__dirname, '.' + filePath[file.fieldname]))
},
filename: function (req, file, cb) {
let name = new Date().toLocaleDateString();
name = name.replace(':','-');
let result = name + '-' + file.originalname;
cb(null, (result))
}
})
exports.Remove = function (path) {
try {
fs.unlinkSync(path);
console.log('successfully deleted' + path);
} catch (err) {
console.log(err);
}
}
exports.upload = multer({storage: storage}).any();
exports.filePath = filePath;
Я объявил пути сохранения файлов, но не дал инструкцию по созданию папок, если они отсутствуют согласно кода:
common : './content/',
imageFile: './uploads/images/',
contentFile: './uploads/content/'
Таким образом, не найдя путь сохранения, программа пожимала плечами и продолжала жить своей жизнью, не видя в этом особой трагедии. Изменения в коде пока не делал, просто добавил папки по нужному пути. Однако, планирую добавить обработчик, чтобы они создавались автоматически при отсутствии.
