Tak ma być za jednym zamachem, to będzie krótko trwało, będzie tylko dopisany do obrazka mały element, obrazki też będą małe, max 20kb. Chodzi mi tylko o sam mechanizm jak to zrobić na podstawie krótkiego przykładu.
No to jeśli nie chcesz zapisywać obrazu na dysku na serwerze, a jednocześnie chcesz dać znać JS'owi że się "udało", to właściwie masz tylko jedno wyjście:
- Rozpocznij upload przez JS'a
- Serwer przyjmuje plik, przetwarza, odpowiada
- JS przechwyuje odpowiedź i plik
- JS wyświetla komunikat userowi
- JS samo rozpoczyna pobieranie pliku w kliencie
Tylko w sumie pytanie. Ten przetworzony obraz ma się pojawić w przeglądarce usera? Czy ma go od razu pobrać?
Ja napisałem że przetworzony obraz się pokazuje, i jest przycisk "Pobierz", ale łatwo dałoby się zrobić żeby od razu się pobierało.
index.html
:
<!DOCTYPE html>
<html lang="pl">
<head>
<title>Upload image</title>
<style>
div#success {
display: none;
}
p#success-text {
padding: 1rem;
color: darkgreen;
border: 1px solid green;
}
p#error-text {
display: none;
padding: 1rem;
color: maroon;
border: 1px solid red;
}
</style>
</head>
<body>
<p>Wybierz obraz JPEG:</p>
<form method="POST" action="upload.php" enctype="multipart/form-data">
<input name="file" type="file"/>
<p>
<button>Upload image</button>
</p>
</form>
<div id="success">
<p id="success-text"></p>
<img/>
<p>
<a>Pobierz</a>
</p>
</div>
<p id="error-text"></p>
<script>
window.addEventListener('load', onLoad);
function onLoad() {
const form = window.document.forms[0];
const fileInput = window.document.getElementsByName("file")[0];
form.addEventListener('submit', event => {
event.preventDefault();
const formData = new FormData();
formData.append('file', fileInput.files[0]);
processFile(form.action, formData);
});
}
function processFile(input, formData) {
fetch(input, {method: 'POST', body: formData})
.then(response => {
if (response.status === 200) {
response.blob()
.then(result => URL.createObjectURL(result))
.then(onSuccess);
}
if (response.status === 400) {
response.json().then(onError);
}
});
}
function onSuccess(imageUrl) {
const successBox = document.getElementById("success");
successBox.style.display = 'block';
const image = successBox.getElementsByTagName("img")[0];
image.src = imageUrl;
const text = successBox.getElementsByTagName("p")[0];
text.innerText = 'Przetworzono obraz';
const link = successBox.getElementsByTagName('a')[0];
link.href = imageUrl;
link.download = 'process file.jpeg';
}
function onError(error) {
const errorText = document.getElementById("error-text");
errorText.innerText = error.message;
errorText.style.display = 'block';
}
</script>
</body>
</html>
upload.php
<?php
function processImageJpeg(string $filePath): void
{
$image = imageCreateFromJpeg($filePath);
$colorWhite = imageColorAllocate($image, 255, 255, 255);
imageString($image, 3, 10, 10, 'This is my sample text', $colorWhite);
imageJpeg($image);
imageDestroy($image);
}
function error(string $errorText): void
{
header('Content-Type: application/json');
http_response_code(400); // bad request
echo \json_encode(['message' => $errorText]);
}
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
http_response_code(405); // method not allowed
return;
}
if (!array_key_exists('file', $_FILES)) {
error('No file uploaded');
return;
}
$filePath = $_FILES['file']['tmp_name'];
$fileInfo = getImageSize($filePath);
if ($fileInfo === false) {
error('Not an image file.');
return;
}
if ($fileInfo['mime'] !== 'image/jpeg') {
error('Only JPEG images are supported.');
return;
}
http_response_code(200);
header('Content-Type: image/jpeg');
processImageJpeg($filePath);