Ładowanie obrazu do <img> z <plik wejściowy>


86

Próbuję załadować obraz wybrany przez użytkownika za pomocą elementu.

Dodałem obsługę zdarzeń onchange do elementu wejściowego w następujący sposób:

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

a funkcja preview_2 to:

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

gdzie outImage ma wartość id tagu, w którym chcę załadować nowy obraz.

Okazuje się jednak, że onload nigdy się nie dzieje i nie ładuje niczego do html.

Co powinienem zrobić?


Odpowiedzi:


102

W przeglądarkach obsługujących File API możesz użyć konstruktora FileReader do odczytu plików po ich wybraniu przez użytkownika.

Przykład

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.
    }
}

Wsparcie przeglądarki

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

Tam, gdzie interfejs File API nie jest obsługiwany, nie można (w większości przeglądarek dbających o bezpieczeństwo) uzyskać pełną ścieżkę do pliku z pola wejściowego pliku ani uzyskać dostępu do danych. Jedynym realnym rozwiązaniem byłoby przesłanie formularza do ukrytej ramki iframe i wstępne przesłanie pliku na serwer. Następnie, gdy żądanie zostanie zakończone, możesz ustawić źródło obrazu na lokalizację przesłanego pliku.


prawda, więc nie ma sposobu, żebym mógł przesłać obraz wybrany przez użytkownika tak prosto, jak brzmi ...?
Valentina

1
tak, szukam rozwiązań dla przeglądarki x, więc myślę, że spróbuję skorzystać z opcji serwera. Dziękuję Ci bardzo!
Valentina

1
Zastanawiam się, dlaczego konwertować to na DataURL, a nie tylko na adres URL obiektu?
ShrekOverflow

4
Jeśli chcesz wersję synchroniczny, można użyć: URL.createObjectURL(document.getElementById("fileInput").files[0]);.
Константин Ван

1
@ КонстантинВан Musisz upewnić się, że dzwonisz, URL.revokeObjectURLaby zapobiec wyciekom pamięci! developer.mozilla.org/en-US/docs/Web/API/URL/revokeObjectURL
Dzień

53

Jak powiedział iEamin w swojej odpowiedzi, HTML 5 obsługuje to teraz. Link, który podał, http://www.html5rocks.com/en/tutorials/file/dndfiles/ , jest doskonały. Oto minimalna próbka oparta na próbkach z tej witryny, ale zobacz tę witrynę, aby uzyskać dokładniejsze przykłady.

Dodaj onchangedetektor zdarzeń do kodu HTML:

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

Utwórz tag obrazu z identyfikatorem (określam, height=200czy obraz nie jest zbyt duży na ekranie):

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

Oto JavaScript onchangenasłuchiwania zdarzeń. Pobiera Fileobiekt, który został przekazany jako event.target.files[0], konstruuje a, FileReaderaby odczytać jego zawartość i konfiguruje nowy detektor zdarzeń, aby przypisać wynikowy data:adres URL do imgtagu:

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);
}

Świetny link! Kod, który przedstawiasz dla skryptu, nie jest jednak zdefiniowany.
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">

To działa dla mnie w jQuery.


Jak tego użyć, jeśli „imgload” i „imgshow” nie są wcześniej zdefiniowane? Powiedzmy, że mam 5 par danych wejściowych pliku i posiadacza obrazu zwróconych z serwera, a ich odpowiednie identyfikatory są generowane na podstawie jakiegoś indeksu, który jest również zwracany z kodu serwera.
Ivan

5

ES2017 Way

// 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);


1

Andy E ma rację, że nie ma na to sposobu opartego na HTML *; ale jeśli chcesz używać Flasha, możesz to zrobić. Poniższe działa niezawodnie w systemach z zainstalowanym Flash. Jeśli Twoja aplikacja musi działać na iPhonie, oczywiście będziesz potrzebować rozwiązania zastępczego opartego na HTML.

* ( Aktualizacja 22.04.2013: HTML obsługuje to teraz w HTML5. Zobacz pozostałe odpowiedzi).

Przesyłanie plików Flash ma również inne zalety - Flash daje możliwość wyświetlania paska postępu w miarę postępu przesyłania dużego pliku. (Jestem prawie pewien, że tak robi to Gmail, używając Flasha za kulisami, chociaż mogę się co do tego mylić).

Oto przykładowa aplikacja Flex 4, która pozwala użytkownikowi wybrać plik, a następnie go wyświetlić:

<?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>

Aby wyjaśnić, dla tych, którzy martwią się o bezpieczeństwo: Flash nie pozwala na dostęp do ŻADNEGO pliku lokalnego - pozwala tylko na dostęp do pliku lokalnego, który został wyraźnie wskazany interaktywnie przez użytkownika. Jest to podobne do tego, co robi HTML (umożliwia przesłanie dowolnego wyraźnie określonego pliku na serwer), z tym wyjątkiem, że Flash umożliwia również dostęp lokalny oprócz możliwości przesłania pliku.
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>

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.