Отправка на сервер картинок React + Node
22.02.2024, 00:12. Показов 731. Ответов 0
Хотел узнать, как можно попробовать загружать с ПК картинку и отправлять ее на какой-нибудь сервис с собственным API, после чего получать оттуда ссылку на картинку и сразу записывать ее в БД. У меня есть код из следующих файлов:
1. DragDrop.js
| JavaScript | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
| import React from "react";
import './DragDrop.css'
import { useTranslation } from 'react-i18next';
import axios from "axios";
const sendDataToServer = async (imageUrl) => {
try {
const formData = new FormData();
formData.append("file", imageUrl);
// Отправка данных на сервер
const response = await axios.post("/api/uploadFile", formData, {
headers: {
"Content-Type": "multipart/form-data",
},
});
if (response.status === 200) {
console.log("Фотография успешно загружена");
// Здесь можно выполнить дополнительные действия после успешной загрузки
} else {
console.error("Ошибка при загрузке фотографии:", response.statusText);
}
} catch (error) {
console.error("Ошибка при загрузке фотографии:", error.message);
}
};
// drag drop file component
function DragDropFile() {
const {t, i18n} = useTranslation()
// drag state
const [dragActive, setDragActive] = React.useState(false);
// ref
const inputRef = React.useRef(null);
// handle drag events
const handleDrag = function(e) {
e.preventDefault();
e.stopPropagation();
if (e.type === 'dragenter' || e.type === 'dragover') {
setDragActive(true);
} else if (e.type === 'dragleave') {
setDragActive(false);
}
};
// triggers when file is dropped
const handleDrop = async function(e) {
e.preventDefault();
setDragActive(false);
if (e.target.files && e.target.files.length > 0) {
handleFile(e.target.files);
await sendDataToServer(e.dataTransfer.files[0]);
}
else {
console.error('Нет загруженных файлов');
}
};
function handleFile(files) {
alert("Number of files: " + files.length);
}
// triggers when file is selected with click
const handleChange = async function(e) {
e.preventDefault();
if (e.target.files && e.target.files.length > 0) {
console.log("Выбран файл:", e.target.files[0]);
handleFile(e.target.files);
await sendDataToServer(e.target.files[0]);
}
else {
console.error('Нет загруженных файлов');
}
};
// triggers the input when the button is clicked
const onButtonClick = (e) => {
e.preventDefault();
inputRef.current.click();
};
return (
<form className="element-animation" id="form-file-upload" onDragEnter={handleDrag} onSubmit={(e) => e.preventDefault()}>
<input ref={inputRef} type="file" id="input-file-upload" multiple={true} onChange={handleChange} />
<label id="label-file-upload" htmlFor="input-file-upload" className={dragActive ? "drag-active" : "" }>
<div>
<p>{t('post.pic')}</p>
<button className="upload-button" onClick={onButtonClick}>{t('post.picButton')}</button>
</div>
</label>
{ dragActive && <div id="drag-file-element" onDragEnter={(e) => e.preventDefault()} onDragLeave={(e) => e.preventDefault()} onDragOver={(e) => e.preventDefault()} onDrop={handleDrop}></div> }
</form>
);
};
export default DragDropFile; |
|
2. Form.js
| JavaScript | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
| import React, { useState } from "react";
import { useTranslation } from "react-i18next";
import Modal from "./Modal/Modal";
import { useInput } from "../hooks/use-form-validate";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faPersonCircleCheck } from "@fortawesome/free-solid-svg-icons";
import DragDropFile from "./DragNDrop/DragDrop.js";
import axios from "axios";
const sign = <FontAwesomeIcon icon={faPersonCircleCheck} size="2x" marginRight="10px" />;
function Form() {
const [modalActive, setModalActive] = useState(false);
const handleSubmit = async (imageUrl) => {
try {
const response = await axios.post("/api/addData", {
imageUrl: imageUrl, // Передаем URL загруженного изображения
title: title.value,
link: link.value,
text: text.value
});
if (response.status === 200) {
console.log("Данные успешно отправлены на сервер");
await sendDataToServer(imageUrl);
// setModalActive(true); // Показываем модальное окно об успешной отправке
} else {
console.error("Ошибка при отправке данных на сервер:", response.statusText);
}
} catch (error) {
console.error("Ошибка при отправке данных на сервер:", error.message);
}
};
const sendDataToServer = async (imageFile) => {
try {
const formData = new FormData();
formData.append("file", imageFile);
// Отправка изображения на сервер
const response = await axios.post("/api/uploadFile", formData, {
headers: {
"Content-Type": "multipart/form-data",
},
});
if (response.status === 200) {
console.log("Фотография успешно загружена");
// Вызываем handleSubmit после успешной загрузки изображения
handleSubmit(response.data.imageUrl);
} else {
console.error("Ошибка при загрузке фотографии:", response.statusText);
}
} catch (error) {
console.error("Ошибка при загрузке фотографии:", error.message);
}
};
// const handleFilesDrop = async (files) => {
// try {
// const formData = new FormData();
// formData.append("file", files[0]);
// const response = await axios.post("/api/uploadPhoto", formData, {
// headers: {
// "Content-Type": "multipart/form-data"
// }
// });
// console.log("Ответ сервера:", response);
// if (response.status === 200) {
// console.log("Фотография успешно загружена");
//
// } else {
// console.error("Ошибка при загрузке фотографии:", response.statusText);
// }
// } catch (error) {
// console.error("Ошибка при загрузке фотографии:", error.message);
// }
// };
// Форма валидации
const { t } = useTranslation();
const title = useInput("", { isEmpty: true, minLength: 5 });
const link = useInput("", { isEmpty: true, minLength: 2 });
const pic = useInput("", { isEmpty: true, minLength: 1 });
const text = useInput("", { isEmpty: true, minLength: 2 });
return (
<form className="contact__form" onSubmit={handleSubmit}>
<div className="input__data">
<input
onBlur={title.onBlur}
value={title.value}
onChange={title.onChange}
className="name__input input form__control element-animation"
type="text"
placeholder={t("post.title")}
name="title"
required
/>
{title.isDirty && title.isEmpty && <div className="form__error">{t("error.empty")}</div>}
{title.isDirty && title.minLengthError && (
<div className="form__error">{t("error.length")}</div>
)}
</div>
<div className="input__data">
<input
onBlur={link.onBlur}
value={link.value}
onChange={link.onChange}
className="link__input input form__control element-animation"
type="text"
placeholder={t("post.link")}
name="link"
required
/>
{link.isDirty && link.isEmpty && <div className="form__error">{t("error.empty")}</div>}
{link.isDirty && link.minLengthError && (
<div className="form__error">{t("error.length")}</div>
)}
</div>
<DragDropFile sendDataToServer={sendDataToServer}/>
<div className="input__data">
<textarea
onBlur={text.onBlur}
value={text.value}
onChange={text.onChange}
className="form__textarea form__control element-animation"
name="text"
id="text"
placeholder={t("post.text")}
></textarea>
{text.isDirty && text.isEmpty && <div className="form__error">{t("error.empty")}</div>}
{text.isDirty && text.minLengthError && (
<div className="form__error">{t("error.length")}</div>
)}
</div>
<button
disabled={!title.inputValid || !link.inputValid || !text.inputValid}
className="form__btn form__control element-animation"
type="submit"
name="submit"
>
{t("post.button")}
</button>
<Modal active={modalActive} setActive={setModalActive}>
{sign}
<p>{t("contact.modalThanks")}</p>
<br />
<p>{t("contact.modalRequest")}</p>
</Modal>
</form>
);
}
export default Form; |
|
3. server.js
| JavaScript | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
| // Импортируем необходимые зависимости
const express = require('express');
const bodyParser = require('body-parser');
const mysql = require('mysql');
const cors = require('cors');
//const cloudinary = require('cloudinary').v2;
const multer = require('multer');
import {v2 as cloudinary} from 'cloudinary';
cloudinary.config({
cloud_name: 'droi2nd1z',
api_key: '598973367993171',
api_secret: '***************************'
});
const connection = mysql.createConnection({
host: 'localhost',
user: 'root',
password: '************',
database: 'wtf_db'
});
const upload = multer({ dest: 'uploads/' });
connection.connect((err) => {
if (err) {
console.error('Ошибка подключения к базе данных:', err);
throw err;
}
console.log('Подключение к базе данных успешно установлено');
});
// Создаем экземпляр express
const app = express();
// Используем middleware для обработки JSON данных
app.use(bodyParser.json());
app.use(cors());
// Определяем маршрут для обработки POST запросов
// app.post("/api/addData", upload.single('file'), async (req, res) => {
// // Получаем данные из тела запроса
// const { title, link, pic, text } = req.body;
// // Выполняем операции с базой данных
// const sql = `INSERT INTO past_orders_info (Header, link, photo, description) VALUES (?, ?, ?, ?)`;
// connection.query(sql, [title, link, pic, text], (err, result) => {
// if (err) {
// console.error('Ошибка выполнения SQL запроса:', err);
// res.status(500).send('Ошибка сервера');
// return;
// }
// console.log('Данные успешно добавлены в базу данных');
// res.status(200).send('Данные успешно добавлены в базу данных');
// });
// });
// app.post("/api/uploadFile", upload.single('file'), async (req, res) => {
// if (!req.files || Object.keys(req.files).length === 0) {
// return res.status(400).send('Нет загруженных файлов.');
// }
//const file = req.files.file;
try {
const result = await cloudinary.uploader.upload(req.file.path);
console.log('File uploaded to Cloudinary:', result);
res.status(200).send(result.secure_url);
} catch (error) {
console.error('Error uploading file to Cloudinary:', error);
res.status(500).send('Internal server error');
}
// cloudinary.uploader.upload(file.tempFilePath, (error, result) => {
// if (error) {
// console.error('Ошибка при загрузке фотографии в Cloudinary:', error);
// return res.status(500).send('Ошибка сервера');
// }
console.log('Фотография успешно загружена в Cloudinary:', result);
const imageUrl = result.secure_url;
res.status(200).send(imageUrl);
// });
// Устанавливаем порт, на котором будет работать сервер
const port = process.env.PORT || 3000;
// Запускаем сервер на выбранном порту
app.listen(port, () => {
console.log(`Сервер запущен на порту ${port}`);
}); |
|
Как видно из кода, я пытался сделать что-то дельное с облачным сервисом cloudinary, который вряд ли даст что-то с ним сделать, хоть я и смог авторизоваться через GH-аккаунт с помощью VPN. Хочется понять, в правильном ли я вообще направлении иду и пользовался ли кто-нибудь эти облачным сервисом в последнее время? Какие есть аналоги подобного сервиса со своими API? Если будут какие-либо советы по правке кода и возможному решению моей задачи - буду безумно признателен!!
0
|