Aynı dosya için girdi türü = dosya "değişikliği" nasıl tespit edilir?


132

Kullanıcı bir dosya seçtiğinde bir olayı tetiklemek istiyorum. Bunu .changeolay ile yapmak , kullanıcı her seferinde dosyayı değiştirirse çalışır.

Ancak kullanıcı aynı dosyayı tekrar seçerse olayı tetiklemek istiyorum.

  1. Kullanıcı seçme dosyası A.jpg(olay tetiklenir)
  2. Kullanıcı seçme dosyası B.jpg(olay tetiklenir)
  3. Kullanıcı dosya seç B.jpg(olay tetiklenmiyor, ateşlemesini istiyorum)

Nasıl yapabilirim?

Yanıtlar:


78

Onu kandırabilirsin. Dosya öğesini kaldırın ve changeolayda aynı yere ekleyin . Dosya yolunu silecek ve her seferinde değişebilir.

JsFiddle ile ilgili örnek.

Veya basitçe kullanabilirsiniz .prop("value", ""), jsFiddle'daki bu örneğe bakın .

  • jQuery 1.6+ prop
  • Önceki versiyonlar attr

@Pekka: Tam olarak değil. Ama onu uyarlayabilir. Diyelim ki dosyayı göndermesi gerekiyor. Gönderiden sonra, yeni dosya seçiciyi kaldıracak ve ekleyecek bir js işlevini çağırabilir. Yapılabilir.
BrunoLM

3
kullandığınızda unutmayın .attr("value", "")veya .val("")(aşağıda @ Wagner-Leonardi önerdiği gibi) krom yok ederken internet explorer değişim etkinliğini ateş edeceği
fadomire

4
"değer" bir özellik olduğundan ve girdinin bir özniteliği olmadığından, önerilen jQuery kullanımı şu şekilde olacaktır.prop("value", "")
Roger Barreto,

70

Denediyseniz .attr("value", "")ve çalışmadıysanız panik yapmayın (benim yaptığım gibi)

sadece .val("")bunun yerine yap ve iyi çalışacak


49

Kullanıcı denetimi her tıkladığında dosya yolunu null olarak ayarlayabilirsiniz . Artık kullanıcı aynı dosyayı seçse bile onchange olayı tetiklenecektir.

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

2
Böyle bir çözüme ihtiyacım vardı. Gerçekten kısa ve işi hallediyor. İyi düşünmüş Mariusz Wiazowski.
Jay Dharmendra Solanki

Diğer bir çözüm, giriş etiketi değiştiğinde değeri değiştirmektir. Ancak bir dosya seçtikten sonra değerin değişmesini beklemiyoruz.
songgeb

1
Harika, öğeyi kaldırıp tekrar doma eklemekten çok daha iyi, thx
David Dal Busco

24

Kullanıcı alanı her tıkladığında hedef girişin değerini temizlemek için onClick olayını kullanın. Bu, onChange olayının aynı dosya için de tetiklenmesini sağlar. Benim için çalıştı :)

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

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

TypeScript kullanma

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

17

Bunu, onClick dosya giriş değerini temizleyerek ve ardından dosyayı Değiştir'e göndererek çalıştırdım. Bu, kullanıcının aynı dosyayı arka arkaya iki kez seçmesine ve yine de değişiklik olayının sunucuya gönderilmek üzere tetiklenmesine olanak tanır. Benim örnek kullanır jQuery formu eklentisi .

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

onClickdaha önce patlıyor onChange, bu yüzden bu yöntem benim için harika çalışıyor.
iplus26

8

Bu benim için çalışıyor

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

1
sanırım function () {this.value = null; yanlış dönüş; }
Jacek Pietal

7

VueJs çözümü

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

1
Bu varyasyon yanıtı için teşekkür ederiz
Coisox

5

@Braitsch'den ilham alarak AngularJS2'imde aşağıdakileri kullandım 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);
    }
}

İşte onClick(event)kurtarılmış beni :-)


4

İşte benim için işe yarayan bulduğum React-y yolu çözümü:

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


3

Muhtemelen yapabileceğiniz en kolay şey, değeri boş bir dizeye ayarlamaktır. Bu, aynı dosya yeniden seçilse bile her seferinde dosyayı 'değiştirmeye' zorlar.

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


2

JQuery kullanmak istemiyorsanız

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

Firefox'ta iyi çalışıyor, ancak Chrome için this.value=null;uyarıdan sonra eklemeniz gerekiyor .


2

Varsayılan olarak, girdinin birden çok özniteliği varsa, dosyalar seçildikten sonra girdi öğesinin value özelliği temizlenir. Bu özelliği temizlemezseniz, aynı dosyayı seçerseniz "change" olayı tetiklenmeyecektir. Bu davranışı multipleözniteliği kullanarak yönetebilirsiniz .

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

Referans


1

Sen yapamaz change(hiçbir şey değişmedi beri, doğru davranış) Buraya yangını. Bununla birlikte, siz de bağlanabilirsiniz click... ancak bu çok sık ateş edebilir ... ikisi arasında çok fazla orta yol yoktur.

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

Görünüşe göre sadece sözlerini tekrarlıyorsunuz ve .click()"yeniden seçimde ateş" değilsiniz.
BrunoLM

@BrunoLM - Hayır, değil ... ama sanırım bunu yapamazsın dediğim kısmı okudun click, olabildiğince yakın.
Nick Craver

1

Giriş için bir tıklama olayı ve bir değişiklik olayı oluşturun. Click olayı girdiyi boşaltır ve change olayı yürütmek istediğiniz kodu içerir.

Dolayısıyla, giriş düğmesine tıkladığınızda tıklama olayı boş olacaktır (dosya seçme pencereleri açılmadan önce), bu nedenle bir dosya seçtiğinizde değişiklik olayı her zaman tetiklenecektir.

$("#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()Dosya girişi fileslistesini temizlemek için kullanabilirsiniz . Bu, tüm alanları varsayılan değerlere sıfırlayacaktır, ancak çoğu durumda, dosyaları yine de yüklemek için bir formda yalnızca input type = 'file' kullanıyor olabilirsiniz. Bu çözümde, elemanın klonlanmasına ve olayların yeniden bağlanmasına gerek yoktur.

Philiplehmann sayesinde


0

Aynı sorunla karşılaştım, yukarıdaki çözümleri gözden geçirdim ancak gerçekte ne olduğuna dair iyi bir açıklama alamadılar.

Https://jsfiddle.net/r2wjp6u8/ yazdığım bu çözüm DOM ağacında çok fazla değişiklik yapmıyor, sadece giriş alanının değerlerini değiştiriyor. Performans açısından biraz daha iyi olmalı.

Keman bağlantısı: 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

Bu nedenle, her bir dosyayı saklamadığınız ve bunları programlı olarak karşılaştırmadığınız sürece, aynı dosyayı seçtiklerinden% 100 emin olmanın bir yolu yoktur.

Dosyalarla etkileşim kurma şekliniz (kullanıcı bir dosyayı 'yüklediğinde' JS'nin yaptığı şey) HTML5 Dosya API'si ve JS Dosya Okuyucusudur .

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

Bu eğitimler, bir dosya karşıya yüklendiğinde (js nesnesi olarak saklanan) meta verileri nasıl yakalayacağınızı ve okuyacağınızı gösterir.

Geçerli dosyanın meta verilerini önceki dosyalarla okuyacak -> depolayacak -> karşılaştıracak 'onChange'i çalıştıran bir işlev oluşturun. Ardından, istediğiniz dosya seçildiğinde etkinliğinizi tetikleyebilirsiniz.


0

İnanın bana, kesinlikle size yardımcı olacaktır!

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

Umarım bu, çoğunuza yardımcı olur.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.