Как загрузить изображения на сервер ExpressJS - PullRequest
2 голосов
/ 20 января 2020

Мне кажется, что я схожу с ума, пытаясь решить эту проблему. Я довольно новый веб-разработчик (это как мой третий настоящий проект), и я пытаюсь создать одностраничное приложение с функцией загрузки изображений. Я использовал AJAX для взаимодействия с внешним и внутренним интерфейсом, поэтому мой первый вопрос: можно ли отправлять изображения с использованием AJAX? Я слышал, что некоторые люди говорят, что это так, а некоторые говорят, что нет, без тонны подробностей о том, почему, или если это так, как.

Я искал другие способы сделать это и нашли очень мало того, что на самом деле содержало достаточно деталей / контекста для реализации. Мне удалось получить что-то, что технически работает, используя базовую c HTML форму и пакет multer npm, который выглядит так:

editModal.innerHTML =   "<img class='thumbnail' src='" + response[0].image_loc + "'><br>" +
                        "<form method='post' action='/upload' enctype='multipart/form-data' id='edit_post_form'>" +
                        "   Select a new thumbnail<input type='file' id='post_thumbnail' name='file'><br>" +
                        "   Title<input type='text' id='post_title' name='title' value='" + response[0].title + "'><br>" +
                        "   Description<input type='text' id='post_desc' name='description' value='" + response[0].description + "'><br>" +
                        "   Price<input type='text' id='post_price' name='price' value='" + response[0].price + "'><br>" +
                        "   <button type='submit' class='submit' id='submit_post_edit'>Submit</button>" +
                        "   <button type='button' class='cancel' id='cancel_post_edit'>Cancel</button>" +
                        "</form>";
app.post('/upload', upload.single("file"), function(req, res) {

    const tempPath = req.file.path;
    const targetPath = path.join(__dirname, "./Assets/Images/image.png");

    console.log(req.file);

    if (path.extname(req.file.originalname).toLowerCase() === "png"
        || path.extname(req.file.originalname).toLowerCase() === "jpg") {

        fs.rename(tempPath, targetPath, function(err) {

            if (err) res.status(400).send({status: "Failure Internal server error"});
            else res.status(200).send({status: "Success"});
        });
    }
    else {
        fs.unlink(tempPath, function(err) {

            if (err) res.status(400).send({status: "Failure Internal server error"});
            else res.status(403).send({status: "Failure Internal server error"});
        })
    }
})

Проблема в том, что это реализация, как и ожидалось, перенаправляет пользователя со страницы к возвращаемому файлу JSON. Есть ли способ обойти это? Я видел, как некоторые предлагают написать функцию .onsubmit, которая возвращает false, и использовать какой-то JQuery для отправки файла в этой функции. У меня есть функция .onsubmit, которую я использую для отправки текстовых полей непосредственно в базу данных, и я попытался вернуть из нее значение false, и оно все еще перенаправляет, поэтому я тоже застрял там.

form.onsubmit = function() {

    var title = document.getElementById("post_title").value;
    var description = document.getElementById("post_desc").value;
    var price = document.getElementById("post_price").value;

    $.ajax({
        url: "DBRequest",
        type: "POST",
        async: false,
        data: { data:
                JSON.stringify(
                { query: "UPDATE post SET title = $1, description = $2, price = $3 WHERE pid = $4",
                  vars: [title, description, price, postID],
                  type: "update"})}
    }).done(function(response) {
        document.body.removeChild(document.getElementById("post_edit_modal"));
        populate();
    });

    return false;
}

Если ответ на оба вопроса - нет, то как это обычно делается? И есть ли место, где я могу подробно прочитать о том, как этот процесс работает? Это кажется очень распространенным явлением.

Ответы [ 2 ]

0 голосов
/ 26 января 2020

Хорошо, для всех, у кого есть эта проблема, вот общее решение, которое мне удалось собрать, используя AJAX:

HTML:

<input type='file' id='file' name='file'>
<button type='button' class='submit' id='submit'>Submit</button>

на стороне клиента JS:

submit = document.getElementById("submit");

submit.onclick = function() {

    var fileData = $("#file").prop("files")[0];
    var formData = new FormData;
    formData.append("file", fileData);

    $.ajax({
        url: "upload",
        dataType: "text",
        cache: false,
        contentType: false,
        processData: false,
        data: formData,
        type: "POST",
    }).done(function(response) {
        //Handle success
    }).catch(function(err) {
        //Handle error
    });
}

На стороне сервера JS:

let multer = require("multer");

const upload = multer({ dest: "/Images" });

app.post('/upload', upload.single("file"), function(req, res) {

    const tempPath = req.file.path;
    const targetPath = path.join(__dirname, "./Assets/Images/" + req.file.originalname);

    if (path.extname(req.file.originalname).toLowerCase() === ".png"
        || path.extname(req.file.originalname).toLowerCase() === ".jpg") {

        fs.rename(tempPath, targetPath, function(err) {

            if (err) res.status(400).send({status: "Failure: Internal server error"});
            else res.status(200).send({status: "Success"});
        });
    }
    else {
        fs.unlink(tempPath, function(err) {

            if (err) res.status(400).send({status: "Failure: Internal server error"});
            else res.status(403).send({status: "Failure: Internal server error"});
        })
    }
})

Это приведет к загрузке одного файла в Assets / Images, если это файл jpg или png.

0 голосов
/ 20 января 2020

Я думаю это - это то, что вы ищете. Предотвращение повторной загрузки страницы или ее переноса в любую точку.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...