Cargar una imagen en un <img> desde <archivo de entrada>

86

Estoy intentando cargar una imagen seleccionada por el usuario a través de un elemento.

Agregué un controlador de eventos onchange al elemento de entrada como este:

<input type="file" name="picField" id="picField" size="24" onchange="preview_2(this);" alt=""/>

y la función preview_2 es:

var outImage ="imagenFondo";
function preview_2(what){
    globalPic = new Image();
    globalPic.onload = function() {
        document.getElementById(outImage).src = globalPic.src;
    }
    globalPic.src=what.value;
}

donde outImage tiene el valor de identificación de la etiqueta donde quiero que se cargue la nueva imagen.

Sin embargo, parece que la carga nunca ocurre y no carga nada en el html.

¿Qué tengo que hacer?

Valentina
fuente
1
duplicados stackoverflow.com/questions/4459379/… ?
desafío

Respuestas:

102

En los navegadores que admiten la API de archivos , puede utilizar el constructor FileReader para leer archivos una vez que el usuario los ha seleccionado.

Ejemplo

document.getElementById('picField').onchange = function (evt) {
    var tgt = evt.target || window.event.srcElement,
        files = tgt.files;

    // FileReader support
    if (FileReader && files && files.length) {
        var fr = new FileReader();
        fr.onload = function () {
            document.getElementById(outImage).src = fr.result;
        }
        fr.readAsDataURL(files[0]);
    }

    // Not supported
    else {
        // fallback -- perhaps submit the input to an iframe and temporarily store
        // them on the server until the user's session ends.
    }
}

Soporte de navegador

  • IE 10
  • Safari 6.0.2
  • Chrome 7
  • Firefox 3.6
  • Opera 12.02

Cuando la API de archivos no es compatible, no puede (en la mayoría de los navegadores conscientes de la seguridad) obtener la ruta completa de un archivo desde un cuadro de entrada de archivos, ni puede acceder a los datos. La única solución viable sería enviar el formulario a un iframe oculto y tener el archivo precargado en el servidor. Luego, cuando esa solicitud se complete, puede establecer el src de la imagen en la ubicación del archivo cargado.

Andy E
fuente
correcto, entonces no hay forma de que pueda subir una imagen seleccionada por el usuario tan simplemente como suena ...?
Valentina
1
sí, estoy buscando soluciones de navegador x, así que creo que lo intentaré usando la opción de servidor. ¡Muchas gracias!
Valentina
1
Me pregunto por qué convertir esto a DataURL y no solo a una URL de objeto.
ShrekOverflow
4
Si quieres la versión sincrónica, puede utilizar: URL.createObjectURL(document.getElementById("fileInput").files[0]);.
Константин Ван
1
@ КонстантинВан ¡Debe asegurarse de llamar URL.revokeObjectURLpara evitar pérdidas de memoria! developer.mozilla.org/en-US/docs/Web/API/URL/revokeObjectURL
Dai
53

Como dijo iEamin en su respuesta, HTML 5 ahora admite esto. El enlace que dio, http://www.html5rocks.com/en/tutorials/file/dndfiles/ , es excelente. Aquí hay una muestra mínima basada en las muestras de ese sitio, pero consulte ese sitio para obtener ejemplos más completos.

Agregue un onchangedetector de eventos a su HTML:

<input type="file" onchange="onFileSelected(event)">

Cree una etiqueta de imagen con una identificación (estoy especificando height=200para asegurarme de que la imagen no sea demasiado grande en pantalla):

<img id="myimage" height="200">

Aquí está el JavaScript del onchangedetector de eventos. Toma el Fileobjeto que se pasó como event.target.files[0], construye un FileReaderpara leer su contenido y configura un nuevo detector de eventos para asignar la data:URL resultante a la imgetiqueta:

function onFileSelected(event) {
  var selectedFile = event.target.files[0];
  var reader = new FileReader();

  var imgtag = document.getElementById("myimage");
  imgtag.title = selectedFile.name;

  reader.onload = function(event) {
    imgtag.src = event.target.result;
  };

  reader.readAsDataURL(selectedFile);
}
Mike Morearty
fuente
¡Gran enlace! Sin embargo, el código que presenta para el script no está definido.
rashadb
13

$('document').ready(function () {
    $("#imgload").change(function () {
        if (this.files && this.files[0]) {
            var reader = new FileReader();
            reader.onload = function (e) {
                $('#imgshow').attr('src', e.target.result);
            }
            reader.readAsDataURL(this.files[0]);
        }
    });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="file" id="imgload" >
<img src="#" id="imgshow" align="left">

Eso me funciona en jQuery.

asghar
fuente
¿Cómo usar esto en caso de que 'imgload' e 'imgshow' no estén definidos de antemano? Digamos que tengo 5 pares de entrada de archivo y soporte de imagen devueltos desde el servidor, y sus respectivos identificadores se generan en función de algún índice que también se devuelve desde el código del servidor.
Ivan
5

ES2017 Camino

// convert file to a base64 url
const readURL = file => {
    return new Promise((res, rej) => {
        const reader = new FileReader();
        reader.onload = e => res(e.target.result);
        reader.onerror = e => rej(e);
        reader.readAsDataURL(file);
    });
};

// for demo
const fileInput = document.createElement('input');
fileInput.type = 'file';
const img = document.createElement('img');
img.attributeStyleMap.set('max-width', '320px');
document.body.appendChild(fileInput);
document.body.appendChild(img);

const preview = async event => {
    const file = event.target.files[0];
    const url = await readURL(file);
    img.src = url;
};

fileInput.addEventListener('change', preview);

nkitku
fuente
1

Andy E tiene razón en que no existe una forma basada en HTML de hacer esto *; pero si está dispuesto a utilizar Flash, puede hacerlo. Lo siguiente funciona de manera confiable en sistemas que tienen Flash instalado. Si su aplicación necesita funcionar en iPhone, entonces, por supuesto, necesitará una solución alternativa basada en HTML.

* ( Actualización 22/4/2013: HTML ahora admite esto, en HTML5. Consulte las otras respuestas).

La carga de Flash también tiene otras ventajas: Flash le brinda la capacidad de mostrar una barra de progreso a medida que avanza la carga de un archivo grande. (Estoy bastante seguro de que así es como lo hace Gmail, al usar Flash entre bastidores, aunque puedo estar equivocado al respecto).

Aquí hay una aplicación de muestra de Flex 4 que permite al usuario elegir un archivo y luego mostrarlo:

<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
               xmlns:s="library://ns.adobe.com/flex/spark" 
               xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600"
               creationComplete="init()">
    <fx:Declarations>
        <!-- Place non-visual elements (e.g., services, value objects) here -->
    </fx:Declarations>
    <s:Button x="10" y="10" label="Choose file..." click="showFilePicker()" />
    <mx:Image id="myImage" x="9" y="44"/>
    <fx:Script>
        <![CDATA[
            private var fr:FileReference = new FileReference();

            // Called when the app starts.
            private function init():void
            {
                // Set up event handlers.
                fr.addEventListener(Event.SELECT, onSelect);
                fr.addEventListener(Event.COMPLETE, onComplete);
            }

            // Called when the user clicks "Choose file..."
            private function showFilePicker():void
            {
                fr.browse();
            }

            // Called when fr.browse() dispatches Event.SELECT to indicate
            // that the user has picked a file.
            private function onSelect(e:Event):void
            {
                fr.load(); // start reading the file
            }

            // Called when fr.load() dispatches Event.COMPLETE to indicate
            // that the file has finished loading.
            private function onComplete(e:Event):void
            {
                myImage.data = fr.data; // load the file's data into the Image
            }
        ]]>
    </fx:Script>
</s:Application>
Mike Morearty
fuente
Para aclarar, para aquellos que están preocupados por la seguridad: Flash no le permite acceder a CUALQUIER archivo local; solo le permite acceder a un archivo local que ha sido señalado explícita e interactivamente por el usuario. Esto es similar a lo que hace HTML (le permite cargar cualquier archivo especificado explícitamente al servidor), excepto que Flash también permite el acceso local además de la capacidad de cargar el archivo.
Mike Morearty
Subí la aplicación Flash ejecutable aquí para que puedas probarla: morearty.com/preview/FileUploadTest.html
Mike Morearty
1

var outImage ="imagenFondo";
function preview_2(obj)
{
	if (FileReader)
	{
		var reader = new FileReader();
		reader.readAsDataURL(obj.files[0]);
		reader.onload = function (e) {
		var image=new Image();
		image.src=e.target.result;
		image.onload = function () {
			document.getElementById(outImage).src=image.src;
		};
		}
	}
	else
	{
		    // Not supported
	}
}
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>preview photo</title>
</head>

<body>
<form>
	<input type="file" onChange="preview_2(this);"><br>
	<img id="imagenFondo" style="height: 300px;width: 300px;">
</form>
</body>
</html>

Saeed saeeyd
fuente