Hola.
Quería dejar por aquí un ejemplo de cómo subir, reducir y mostrar en vista previa una imagen de un formulario html dinámicamente con Ajax. En realidad no es con Ajax, porque JavaScript no puede manipular un campo archivo (tipo "file"), así que tiene que ser dinámicamente con php.
JavaScript no puede recoger el archivo seleccionado de un campo archivo para enviarlo dinámicamente por motivos de seguridad. La única manera de enviar un archivo es enviar el formulario completo con "submit". Para no enviar el archivo con el resto de los datos del formulario, el campo archivo debe ser un formulario separado del resto de los datos. Así puede enviarse automáticamente cada vez que se seleccione un nuevo archivo, sin afectar al resto de los campos. El archivo seleccionado se envía a un script php que evalúa si es un archivo de imagen válido, y, de ser así, lo sube, redimensiona y devuelve a la página html, a un iframe que muestra la imagen sin recargar la página.
De esta manera, ya se puede enviar con Ajax el resto de los datos del formulario, juntamente con una variable que el script php ha almacenado en el iframe, que contiene la ruta de la imagen subida en el servidor. Se envía a otro scrip php que procesa todos los datos, todo sin tener que recargar la página en ningún momento.
En total se usan un archivo html y dos php (en el siguiente post), que no suman más de 20 KB.
¿Qué os parece el sistema?
Saludos.
Código HTML:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<!--
Author: Alberto Moyano Sánchez
Date: 2009-05-24
Description: [...]
Notes and improvements: [...]
-->
<html>
<head>
<title>
Upload and preview an image with Ajax
</title>
<script language="JavaScript" type="text/javascript">
var loadingHtml = "Loading..."; // this could be an animated image
var imageLoadingHtml = "Image loading...";
var http = getXMLHTTPRequest();
//----------------------------------------------------------------
function uploadImage() {
var uploadedImageFrame = window.uploadedImage;
uploadedImageFrame.document.body.innerHTML = loadingHtml;
// VALIDATE FILE
var imagePath = uploadedImageFrame.imagePath;
if(imagePath == null){
imageForm.oldImageToDelete.value = "";
}
else {
imageForm.oldImageToDelete.value = imagePath;
}
imageForm.submit();
}
//----------------------------------------------------------------
function showImageUploadStatus() {
var uploadedImageFrame = window.uploadedImage;
if(uploadedImageFrame.document.body.innerHTML == loadingHtml){
divResult.innerHTML = imageLoadingHtml;
}
else {
var imagePath = uploadedImageFrame.imagePath;
if(imagePath == null){
divResult.innerHTML = "No uploaded image in this form.";
}
else {
divResult.innerHTML = "Loaded image: " + imagePath;
}
}
}
//----------------------------------------------------------------
function getXMLHTTPRequest() {
try {
xmlHttpRequest = new XMLHttpRequest();
}
catch(error1) {
try {
xmlHttpRequest = new ActiveXObject("Msxml2.XMLHTTP");
}
catch(error2) {
try {
xmlHttpRequest = new ActiveXObject("Microsoft.XMLHTTP");
}
catch(error3) {
xmlHttpRequest = false;
}
}
}
return xmlHttpRequest;
}
//----------------------------------------------------------------
function sendData() {
var url = "submitForm.php";
var parameters = "imageDescription=" + dataForm.imageDescription.value;
var imagePath = window.uploadedImage.imagePath;
if(imagePath != null){
parameters += "&uploadedImagePath=" + imagePath;
}
http.open("POST", url, true);
http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
http.setRequestHeader("Content-length", parameters.length);
http.setRequestHeader("Connection", "close");
http.onreadystatechange = useHttpResponse;
http.send(parameters);
}
//----------------------------------------------------------------
function submitFormIfNotImageLoading(maxLoadingTime, checkingIntervalTime) {
if(window.uploadedImage.document.body.innerHTML == loadingHtml) {
if(maxLoadingTime <= 0) {
divResult.innerHTML = "The image loading has timed up. "
+ "Please, try again when the image is loaded.";
}
else {
divResult.innerHTML = imageLoadingHtml;
maxLoadingTime = maxLoadingTime - checkingIntervalTime;
var recursiveCall = "submitFormIfNotImageLoading("
+ maxLoadingTime + ", " + checkingIntervalTime + ")";
setTimeout(recursiveCall, checkingIntervalTime);
}
}
else {
sendData();
}
}
//----------------------------------------------------------------
function submitForm() {
var maxLoadingTime = 3000; // milliseconds
var checkingIntervalTime = 500; // milliseconds
submitFormIfNotImageLoading(maxLoadingTime, checkingIntervalTime);
}
//----------------------------------------------------------------
function useHttpResponse() {
if (http.readyState == 4) {
if (http.status == 200) {
divResult.innerHTML = http.responseText;
dataForm.reset();
imageForm.reset();
window.uploadedImage.document.body.innerHTML = "";
window.uploadedImage.imagePath = null;
}
}
}
</script>
</head>
<body>
<h3>
Form with preview of resized image with Ajax
</h3>
<form id="dataForm" name="dataForm">
Image description:
<input name="imageDescription" id="imageDescription" type="text"
size="30"/>
</form>
<form id="imageForm" name="imageForm" enctype="multipart/form-data"
action="uploadImage.php" method="POST" target="uploadedImage">
<!-- Next field limits the maximum size of the selected file to 2MB.
If exceded the size, an error will be sent with the file. -->
<input type="hidden" name="MAX_FILE_SIZE" value="2000000" />
Image:
<input name="imageToUpload" id="imageToUpload" type="file"
onchange="uploadImage();" size="30"/>
<br />
Old uploaded image to delete (this field should be hidden):
<br />
<input name="oldImageToDelete" id="oldImageToDelete" type="text"
size="50" />
</form>
<iframe id="uploadedImage" name="uploadedImage" src=""
style="width:200px; height:200px;"
frameborder="0" marginheight="0" marginwidth="0"></iframe>
<br /><br />
<form>
<input type="button" onclick="submitForm();" value="Submit" />
</form>
<br />
<form>
<input type="button" onclick="showImageUploadStatus();" value="Show image upload status" />
</form>
<div id="divResult"></div>
</body>
</html>