Загрузить изображение, хранящееся в объекте JavaScript, в PHP


у меня есть запрос, у меня есть Drag & Drop, который хранит мне изображение как объект в переменной JavaScript, как я мог бы сделать, чтобы отправить этот объект в PHP и сохранить изображение в базе данных как тип BLOB?

Так что у меня есть HTML-код

         <div class="drag-area">
            <div class="icon"><i class="fas fa-cloud-upload-alt"></i></div>
            <div class="img"></div>
            <header>Drag & Drop to Upload File</header>
            <span>OR</span>
            <button>Browse File</button>
            <input type="file" hidden name="file" />
        </div>

и JS так, где вы можете видеть, что переменная file хранит изображение, которое загружается при нажатии кнопки или перетаскивании изображения в dropArea, когда я делаю запрос fetch и я передаю в тело formData по прибытии на сервер, он не сохраняет его и просто показывает мне в ответе как Undefined. Я не очень хорошо знаю PHP в глубине, но если мне нужно иметь возможность исправить недостаток и узнать, потому что он не получает изображение.

const dropArea = document.querySelector(".drag-area"),
    dragText = dropArea.querySelector("header"),
    icon = dropArea.querySelector(".icon"),
    button = dropArea.querySelector("button"),
    input = dropArea.querySelector("input"),
    img = dropArea.querySelector(".img");
let file; 

button.onclick = () => {
    input.click();
};


input.addEventListener("change", function () {
// Esta variable file es donde se almacena el archivo como un objeto
    file = this.files[0];
    dropArea.classList.add("active");
    showFile();
});

dropArea.addEventListener("dragover", (event) => {
    event.preventDefault(); 
    dropArea.classList.add("active");
    dragText.textContent = "Release to Upload File";
});

dropArea.addEventListener("dragleave", () => {
    dropArea.classList.remove("active");
    dragText.textContent = "Drag & Drop to Upload File";
});

dropArea.addEventListener("drop", (event) => {
    event.preventDefault();
    file = event.dataTransfer.files[0];
});

// Esta funcion valida la extension de la imagen y la renderiza para insertarla por pantalla
function showFile() {
    let fileType = file.type; 
    let validExtensions = ["image/jpeg", "image/jpg", "image/png"];
    if (validExtensions.includes(fileType)) {
        let fileReader = new FileReader(); 
        fileReader.onload = () => {
            let fileURL = fileReader.result; 
            var imgTag = `<img src="${fileURL}" alt="" id="foto">`;
            img.innerHTML = imgTag;
            dragText.classList.add("none");
            button.classList.add("none");
            icon.classList.add("none");
        };
        fileReader.readAsDataURL(file);
    } else {
        alert("This is not an Image File!");
        dropArea.classList.remove("active");
        dragText.textContent = "Drag & Drop to Upload File";
    }
}

 // Aqui hago la peticion fetch
    enviar.addEventListener("click", () => {
        fetch("enviar.php", {
            method: "POST",
//Aqui envio el formulario
            body: new FormData(form),
        })
            .then((response) => response.text())
            .then((response) => {
                console.log(response);
            });
    });

на сервере я храню его в переменной $Photo и использую функцию addslashes и file_get_contents

define('DB_HOST','localhost');
define('DB_USER','root');
define('DB_PASS','');
define('DB_NAME','example1');

$conn = new mysqli(DB_HOST, DB_USER, DB_PASS, DB_NAME);

if ($conn ->connect_error){
    die ("Conexión fallida: "  . $conn->connect_error);
}

$foto = addslashes(file_get_contents($_FILES['photo_user']['tmp_name']));

$query = "INSERT INTO usuario (foto) VALUES ('$foto')";

$result = $conn->query($query);

if(!$result){
    die("Query Failed: " . mysqli_error($conn));
}else{
    echo "ok";
}
Author: Daniel Carrillo, 2021-04-08

1 answers

В коде, который вы показываете, нет формы, поэтому new FormData(form) будет генерировать ошибку, и в любом случае, если файл был перетащен, он не добавляется в <input type="file">, он остается только в переменной file.

Что вам нужно сделать, это создать пустой объект FormData и использовать метод . append () для добавления файла, предоставляя 2 параметра: nombre, valor.

const dropArea = document.querySelector(".drag-area"),
    dragText = dropArea.querySelector("header"),
    icon = dropArea.querySelector(".icon"),
    button = dropArea.querySelector("button"),
    input = dropArea.querySelector("input"),
    img = dropArea.querySelector(".img"),
    enviar = document.querySelector('#enviar');
let file; 

button.onclick = () => {
    input.click();
};


input.addEventListener("change", function () {
// Esta variable file es donde se almacena el archivo como un objeto
    file = this.files[0];
    dropArea.classList.add("active");
    showFile();
});

dropArea.addEventListener("dragover", (event) => {
    event.preventDefault(); 
    dropArea.classList.add("active");
    dragText.textContent = "Release to Upload File";
});

dropArea.addEventListener("dragleave", () => {
    dropArea.classList.remove("active");
    dragText.textContent = "Drag & Drop to Upload File";
});

dropArea.addEventListener("drop", (event) => {
    event.preventDefault();
    file = event.dataTransfer.files[0];
    // Mostrar archivo
    showFile();
});

// Esta funcion valida la extension de la imagen y la renderiza para insertarla por pantalla
function showFile() {
    let fileType = file.type; 
    let validExtensions = ["image/jpeg", "image/jpg", "image/png"];
    if (validExtensions.includes(fileType)) {
        let fileReader = new FileReader(); 
        fileReader.onload = () => {
            let fileURL = fileReader.result; 
            var imgTag = `<img src="${fileURL}" alt="" id="foto">`;
            img.innerHTML = imgTag;
            dragText.classList.add("none");
            button.classList.add("none");
            icon.classList.add("none");
        };
        fileReader.readAsDataURL(file);
    } else {
        alert("This is not an Image File!");
        dropArea.classList.remove("active");
        dragText.textContent = "Drag & Drop to Upload File";
    }
}

// Aqui hago la peticion fetch
enviar.addEventListener("click", (e) => {
    // Evitar comportamiento normal del botón (¿submit?)
    e.preventDefault();
    // Verificar que se agregó un archivo
    if(!file) {
        alert('Agrega un archivo');
        return;
    }
    // Crea un objeto FormData
    let data = new FormData();
    // Agrega el archivo
    data.append('photo_user', file);
    // Solo para ver que sí se agregó el archivo
    console.log(...data);
    fetch("enviar.php", {
        method: "POST",
        body: data,
    })
    .then((response) => response.text())
    .then((response) => {
        console.log(response);
    });
});
<div class="drag-area">
            <div class="icon"><i class="fas fa-cloud-upload-alt"></i></div>
            <div class="img"></div>
            <header>Drag & Drop to Upload File</header>
            <span>OR</span>
            <button>Browse File</button>
            <input type="file" hidden name="file" />
        </div>
        <button id="enviar">Enviar</button>

В PHP вы должны сначала переместить загруженный файл из временное расположение к конечному пути с move_uploaded_file () и создать запись только в том случае, если она может быть перемещена.

// Usar una variable para tratar de simplificar
$file = $_FILES['photo_user'];
// Si la propiedad "error" es cero, el archivo se subió correctamente
if($file['error'] == 0) {
    // "name" contiene el nombre real del archivo
    $foto = $file['name'];
    // Mover el archivo a su ubicación final
    // Revisa que exista la carpeta y tiene permisos de escritura
    if(move_uploaded_file($file['tmp_name'], "ruta/$foto")) {
        // Ahora sí puedes insertar en base de datos
    } else {
        echo 'El archivo se subió, pero no se pudo mover a ubicación final';
    }
} else {
    echo 'No se pudo subir el archivo';
}

В PHP все еще есть важные вещи, которые вы должны исследовать:

  • никогда не доверяйте пользователям, он всегда проверяет, что файл действительно является изображением
  • Не используйте addSlashes() чтобы избежать переменных, которые вы собираетесь включить в запрос, в зависимости от используемой библиотеки есть параметры real_escape_string
  • чтобы избежать ошибок e SQL инъекции лучше использовать подготовленные запросы и, таким образом, вы избегаете "изобретать" вещи, как в предыдущем пункте
  0
Author: Triby, 2021-04-09 20:18:48