JavaScript: Загрузить файл

190

Допустим, у меня есть этот элемент на странице:

<input id="image-file" type="file" />

Это создаст кнопку, которая позволит пользователям веб-страницы выбрать файл через диалоговое окно ОС «Файл открыт ...» в браузере.

Допустим, пользователь нажимает указанную кнопку, выбирает файл в диалоговом окне, а затем нажимает кнопку «ОК», чтобы закрыть диалоговое окно.

Выбранное имя файла теперь сохраняется в:

document.getElementById("image-file").value

Теперь предположим, что сервер обрабатывает многоэлементные сообщения POST по URL-адресу "/ upload / image".

Как отправить файл в «/ upload / image»?

Кроме того, как я могу прослушать уведомление о том, что файл закончил загрузку?

YummyBánhMì
источник
2
JavaScript не обрабатывает загрузки, потому что это сервер. Серверный скрипт получит файл, а затем переместит его. Для php из временной папки в нужную папку.
Бакудан
15
Проголосовал за повторное открытие, потому что вопрос касается POJS (простой старый javascript), а не jQuery.
e2-e4

Ответы:

95

Если вы не пытаетесь загрузить файл с помощью ajax, просто отправьте форму в /upload/image.

<form enctype="multipart/form-data" action="/upload/image" method="post">
    <input id="image-file" type="file" />
</form>

Если вы хотите загрузить изображение в фоновом режиме (например, без отправки всей формы), вы можете использовать ajax:

Мэтт Болл
источник
или iframe размером 0x0 со сценарием загрузки изображений внутри его src = "" и отправьте ему форму, используя target = "iframeId", считывая результат обратно в событие iframe src .load, которое можно связать, например, с помощью jQuery.
Дмитрий
11
На самом деле в настоящее время возможно поднять голосование через Javascript и Ajax, см. Stackoverflow.com/a/10811427/694469 (я не понизил).
КаджМагнус
35
@KajMagnus, вы, вероятно, имели в виду «загрузить», но случайно сказали «upvote»
Сэмюэль Аллан
85

Чистый JS

При желании вы можете использовать fetch с помощью await-try-catch

let photo = document.getElementById("image-file").files[0];
let formData = new FormData();

formData.append("photo", photo);
fetch('/upload/image', {method: "POST", body: formData});

Старый школьный подход - xhr

let photo = document.getElementById("image-file").files[0];  // file from input
let req = new XMLHttpRequest();
let formData = new FormData();

formData.append("photo", photo);                                
req.open("POST", '/upload/image');
req.send(formData);

РЕЗЮМЕ

  • На стороне сервера вы можете прочитать оригинальное имя файла (и другую информацию), которое автоматически включается в запрос браузера filename параметре formData.
  • Вам НЕ нужно устанавливать заголовок запроса Content-Typeнаmultipart/form-data - это будет установлено браузером автоматически.
  • Вместо этого /upload/imageвы можете использовать полный адрес, какhttp://.../upload/image .
  • Если вы хотите отправить много файлов в одном запросе, используйте multipleатрибут: <input multiple type=... />и прикрепите все выбранные файлы к formData аналогичным образом (например, photo2=...files[2];...formData.append("photo2", photo2); )
  • Вы можете включить дополнительные данные (JSON) для запроса, например, let user = {name:'john', age:34} таким образом:formData.append("user", JSON.stringify(user));
  • Это решение должно работать на всех основных браузерах.
Камил Келчевски
источник
Работай идеально для меня.
Триу Нгуен
formData === отправка формыenctype="multipart/form-data"
xgqfrms
Я получаю ошибкуnet::ERR_ABORTED 405 (Method Not Allowed)
Хидайт Рахман
@HidaytRahman эта ошибка обычно появляется, когда сервер не использует метод POST для вашего URL
Камил Келчевски
1
Странно - По вашему заголовку я думал, что нам больше не нужен сервер: D
Хидайт Рахман