Як виявити тип введення = змінити файл для одного файлу?


131

Я хочу запустити подію, коли користувач вибирає файл. Це робиться у .changeвипадку, коли воно працює, якщо користувач кожного разу змінює файл.

Але я хочу запустити подію, якщо користувач знову вибере той самий файл.

  1. Файл вибору користувачем A.jpg(події пожежі)
  2. Файл вибору користувачем B.jpg(події пожежі)
  3. Виберіть файл користувача B.jpg(подія не спрацьовує, я хочу, щоб він запустився)

Як я можу це зробити?

Відповіді:


78

Ви можете це обдурити. Видаліть елемент файлу та додайте його там же, коли changeподія. Це буде стирати шлях до файлу, роблячи його змінним щоразу.

Приклад на jsFiddle.

Або ви можете просто використовувати .prop("value", ""), дивіться цей приклад на jsFiddle .

  • jQuery 1.6+ prop
  • Більш ранні версії attr

@Pekka: Не зовсім так. Але він може просто адаптувати це. Скажімо, йому потрібно опублікувати файл. Після публікації він може зателефонувати у функцію js, яка видалить та додасть новий селектор файлів. Це можливо.
BrunoLM

3
майте на увазі, що коли ви використовуєте .attr("value", "")або .val("")(як це запропонував @ wagner-leonardi нижче), Internet Explorer відкриє подію змін, а хром не зробить
fadomire

4
Оскільки "value" є властивістю, а не атрибутом введення, рекомендованим використанням jQuery було б.prop("value", "")
Roger Barreto

70

Якщо ви спробували .attr("value", "")і не вийшло, не панікуйте (як я)

просто зробіть .val("")замість цього, і буде добре працювати


49

Ви можете просто встановити нульовий шлях до файлу кожного разу, коли користувач натискає на елемент управління. Тепер, навіть якщо користувач вибере той самий файл, подія onchange буде запущено.

<input id="file" onchange="file_changed(this)" onclick="this.value=null;" type="file" accept="*/*" />

2
Мені потрібно таке рішення. Це дійсно коротко і отримує роботу. Приємно думаючи Маріуш Вязовський.
Джей Дхармендра Соланкі

Іншим рішенням є те, що змінюється значення при зміні тегу введення. Але ми не очікуємо, що значення буде змінено після вибору файла.
songgeb

1
Класно, спосіб краще, ніж вилучити та додати елемент у
домі

24

Використовуйте подію onClick, щоб очистити значення цільового вводу кожного разу, коли користувач натискає поле. Це гарантує, що подія onChange буде запущена і для того ж файлу. Для мене працювали :)

onInputClick = (event) => {
    event.target.value = ''
}

<input type="file" onChange={onFileChanged} onClick={onInputClick} />

Використання TypeScript

onInputClick = ( event: React.MouseEvent<HTMLInputElement, MouseEvent>) => {
    const element = event.target as HTMLInputElement
    element.value = ''
}

17

Я отримав це для роботи, очистивши значення вводу файлу onClick і потім опублікувавши файл onChange. Це дозволяє користувачеві вибирати один і той самий файл двічі поспіль і все одно мати повідомлення про події зміни на сервер. У моєму прикладі використовується плагін форми jQuery .

$('input[type=file]').click(function(){
    $(this).attr("value", "");
})  
$('input[type=file]').change(function(){
    $('#my-form').ajaxSubmit(options);      
})

onClickпожежі раніше onChange, тому цей метод для мене чудово працює.
iplus26

8

Ця робота для мене

<input type="file" onchange="function();this.value=null;return false;">

1
я думаю, ти мав на увазі щось на кшталт function () {this.value = null; повернути помилкове; }
Яцек П'єтал

7

Рішення VueJs

<input
                type="file"
                style="display: none;"
                ref="fileInput"
                accept="*"
                @change="onFilePicked"
                @click="$refs.fileInput.value=null"
>

1
Дякую вам за цю варіацію відповіді
Coisox

5

Надихаючись від @braitsch, я використав наступне у своєму AngularJS2 input-file-component

<input id="file" onclick="onClick($event) onchange="onChange($event)" type="file" accept="*/*" />

export class InputFile {

    @Input()
    file:File|Blob;

    @Output()
    fileChange = new EventEmitter();

    onClick(event) {
        event.target.value=''
    }
    onChange(e){
        let files  = e.target.files;
        if(files.length){
            this.file = files[0];
        }
        else { this.file = null}
        this.fileChange.emit(this.file);
    }
}

Тут onClick(event)мене врятували :-)


3

Напевно, найпростіше, що ви можете зробити, це встановити значення в порожній рядок. Це змушує його "змінювати" файл кожного разу, навіть якщо той самий файл буде обраний знову.

<input type="file" value="" />


3

Ось таке рішення React-y, яке я знайшов, що працювало для мене:

onClick={event => event.target.value = null}


2

Якщо ви не хочете використовувати jQuery

<form enctype='multipart/form-data'>
    <input onchange="alert(this.value); return false;" type='file'>
    <br>
    <input type='submit' value='Upload'>
</form>

У Firefox він працює чудово, але для Chrome його потрібно додати this.value=null;після попередження.


2

За замовчуванням властивість значення елемента введення очищається після вибору файлів, якщо вхід має декілька атрибутів. Якщо ви не очистите це властивість, подія "зміни" не запуститься, якщо ви виберете той самий файл. Ви можете керувати такою поведінкою за допомогою multipleатрибута.

<!-- will be cleared -->
<input type="file" onchange="yourFunction()" multiple/>
<!-- won't be cleared -->
<input type="file" onchange="yourFunction()"/>

Довідково


1

Тут не можна changeрозпалювати вогонь (правильна поведінка, оскільки нічого не змінилося). Однак ти можеш також пов'язувати click... хоча це може надто часто стріляти ... Однак між двома місцями не так вже й багато.

$("#fileID").bind("click change", function() {
  //do stuff
});

Здається, ви просто повторюєте його слова і .click()не є "вогнем на повторний вибір".
BrunoLM

@BrunoLM - Ні, це не так ... але я думаю, що ти читаєш частину, де я кажу, що ти не можеш цього зробити click.
Нік Крейвер

1

Створіть для введення подію клацання та подію зміни. Подія клацання очищає вхід, і подія зміни містить код, який потрібно виконати.

Таким чином подія натискання буде порожньою при натисканні кнопки введення (до того, як відкриються вікна вибраних файлів), тому подія зміни завжди спрацьовує, коли ви вибираєте файл.

$("#input").click(function() {
  $("#input").val("")
});

$("#input").change(function() {
  //Your code you want to execute!
});
<input id="input" type="file">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js">
</script>


0

Ви можете form.reset()очистити filesсписок вхідних файлів . Це скине всі поля до значень за замовчуванням, але у багатьох випадках ви можете використовувати лише тип введення = 'файл' у формі для завантаження файлів. У цьому рішенні немає потреби клонувати елемент і повторно підключати події знову.

Завдяки філіплехману


0

Я зіткнувся з тією ж проблемою, і я переконався, що він вирішив вище, але вони не отримали жодного хорошого пояснення, що насправді відбувається.

Це рішення, яке я написав https://jsfiddle.net/r2wjp6u8/ , не робить багато змін у дереві DOM, воно лише змінює значення поля введення. З точки зору продуктивності це повинно бути трохи краще.

Посилання на скрипку: https://jsfiddle.net/r2wjp6u8/

<button id="btnSelectFile">Upload</button>

<!-- Not displaying the Inputfield because the design changes on each browser -->
<input type="file" id="fileInput" style="display: none;">
<p>
  Current File: <span id="currentFile"></span>
</p>
<hr>
<div class="log"></div>


<script>
// Get Logging Element
var log = document.querySelector('.log');

// Load the file input element.
var inputElement = document.getElementById('fileInput');
inputElement.addEventListener('change', currentFile);

// Add Click behavior to button
document.getElementById('btnSelectFile').addEventListener('click', selectFile);

function selectFile() {
  if (inputElement.files[0]) {
    // Check how manyf iles are selected and display filename
    log.innerHTML += '<p>Total files: ' + inputElement.files.length + '</p>'
    // Reset the Input Field
    log.innerHTML += '<p>Removing file: ' + inputElement.files[0].name + '</p>'
    inputElement.value = '';
    // Check how manyf iles are selected and display filename
    log.innerHTML += '<p>Total files: ' + inputElement.files.length + '</p>'
    log.innerHTML += '<hr>'
  }

  // Once we have a clean slide, open fiel select dialog.
  inputElement.click();
};

function currentFile() {
    // If Input Element has a file
  if (inputElement.files[0]) {
    document.getElementById('currentFile').innerHTML = inputElement.files[0].name;
  }
}

</scrip>

0

Отже, немає можливості на 100% бути впевненим, що вони вибирають один і той же файл, якщо ви не зберігаєте кожен файл і не порівнюєте їх програмно.

Спосіб взаємодії з файлами (те, що робить JS, коли користувач "завантажує" файл) - це HTML5 File API та JS FileReader .

https://www.html5rocks.com/en/tutorials/file/dndfiles/

https://scotch.io/tutorials/use-the-html5-file-api-to-work-with-files-locally-in-the-browser

Ці підручники показують вам, як захоплювати та читати метадані (зберігаються як js об’єкт) під час завантаження файлу.

Створіть функцію, яка запускає "onChange", яка буде читати-> зберігати-> порівнювати метадані поточного файлу з попередніми файлами. Тоді ви можете запустити свою подію, коли вибрано потрібний файл.


0

Повірте, це вам точно допоможе!

// there I have called two `onchange event functions` due to some different scenario processing.

<input type="file" class="selectImagesHandlerDialog" 
    name="selectImagesHandlerDialog" 
    onclick="this.value=null;" accept="image/x-png,image/gif,image/jpeg" multiple 
    onchange="delegateMultipleFilesSelectionAndOpen(event); disposeMultipleFilesSelections(this);" />


// delegating multiple files select and open
var delegateMultipleFilesSelectionAndOpen = function (evt) {

  if (!evt.target.files) return;

  var selectedPhotos = evt.target.files;
  // some continuous source

};


// explicitly removing file input value memory cache
var disposeMultipleFilesSelections = function () {
  this.val = null;
};

Сподіваюся, це допоможе багатьом з вас, хлопці.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.