2011-01-07 224 views

回答

17

你不能。

文件對話框的結果不會暴露給瀏覽器。

+0

是否可以檢查文件選擇器是否打開? – Ppp 2011-01-13 14:34:54

+1

@Ppp - 不是。瀏覽器不會告訴你。 「 – Oded 2011-01-13 14:35:31

+4

」文件對話框的結果不會暴露給瀏覽器。「如果通過選擇文件關閉對話框,則不是這樣。 – Trevor 2016-12-01 22:24:29

5

當您選擇一個文件並單擊打開/取消,input元素應該失去焦點。假設input的初始value爲空,則blur處理程序中的任何非空值都表示確定,而空值表示取消。

更新:當隱藏input時,blur未被觸發。因此,除非您想臨時顯示input,否則不能在基於IFRAME的上傳中使用此技巧。

+2

在Firefox 10 beta和Chrome 16中,選擇文件時不會觸發`blur`。沒有在其他瀏覽器中嘗試過。 – Blaise 2012-01-03 12:21:48

+1

這不起作用 - 點擊後立即觸發輸入模糊。 Win7上的Chrome 63.0.3239.84 x64。 – Qwertiy 2017-12-27 17:55:31

5

如果您選擇與先前相同的文件並且單擊取消:在這種情況下,您可以捕獲取消。

你可以這樣說:

<input type="file" id="myinputfile"/> 
<script> 
document.getElementById('myinputfile').addEventListener('change', myMethod, false); 
function myMethod(evt) { 
    var files = evt.target.files; 
    f= files[0]; 
    if (f==undefined) { 
    // the user has clicked on cancel 
    } 
    else if (f.name.match(".*\.jpg")|| f.name.match(".*\.png")) { 
    //.... the user has choosen an image file 
    var reader = new FileReader(); 
    reader.onload = function(evt) { 
     try { 
     myimage.src=evt.target.result; 
      ... 
     } catch (err) { 
      ... 
     } 
    }; 
    }  
    reader.readAsDataURL(f);   
</script> 
+1

Thnkx @loveJs這篇文章真的幫了我。 – VPK 2013-03-20 11:03:25

+3

不完全是,如果用戶選擇相同的文件,它不是取消=( – 2013-11-08 13:27:56

+10

onchange只會在有變化時觸發,所以如果文件與前一個文件相同,則onchange偵聽器不會觸發 – Shane 2014-02-13 00:04:45

0

有一個hackish的方式做到這一點(添加回調或解決某些遞延/承諾執行,而不是alert()電話):

var result = null; 

$('<input type="file" />') 
    .on('change', function() { 
     result = this.files[0]; 
     alert('selected!'); 
    }) 
    .click(); 

setTimeout(function() { 
    $(document).one('mousemove', function() { 
     if (!result) { 
      alert('cancelled'); 
     } 
    }); 
}, 1000); 

工作原理:文件選擇對話框打開時,文檔不會收到鼠標指針事件。有1000毫秒的延遲允許對話框實際出現並阻止瀏覽器窗口。在Chrome和Firefox中檢查(僅限Windows)。

但是,這當然不是一種可靠的檢測取消對話的方式。雖然,可能會改善一些用戶界面行爲。

29

雖然不是直接的解決方案,並且也很糟糕,因爲它只是(據我測試過)的作品與聚焦狀態(需要一個漂亮的限制事件阻塞),你可以用下面的實現它:

document.body.onfocus = function(){ /*rock it*/ } 

這有什麼好處的是,您可以使用文件事件及時附加/分離它,並且它似乎也可以很好地處理隱藏的輸入(如果您使用可視變通辦法來處理蹩腳的默認輸入類型= '文件')。之後,你只需要弄清楚輸入值是否改變了。

一個例子:

var godzilla = document.getElementById('godzilla') 

godzilla.onclick = charge 

function charge() 
{ 
    document.body.onfocus = roar 
    console.log('chargin') 
} 

function roar() 
{ 
    if(godzilla.value.length) alert('ROAR! FILES!') 
    else alert('*empty wheeze*') 
    document.body.onfocus = null 
    console.log('depleted') 
} 

看到它在行動:http://jsfiddle.net/Shiboe/yuK3r/6/

可悲的是,它似乎只WebKit的瀏覽器。也許別人可以找出Firefox/IE解決方案

1

在我的情況下,我不得不隱藏提交按鈕,而用戶選擇圖像。

這就是我想出:

$(document).on('click', '#image-field', function(e) { 
    $('.submit-button').prop('disabled', true) 
}) 
$(document).on('focus', '#image-field'), function(e) { 
    $('.submit-button').prop('disabled', false) 
}) 

#image-field是我的文件選擇。當沒有人點擊它時,我禁用表單提交按鈕。關鍵是,當文件對話框關閉 - 無所謂他們選擇一個文件或取消 - #image-field焦點回來,所以我聽這個事件。

UPDATE

我發現,這並不在Safari和騷靈/ phantomjs工作。如果你想實施它,請考慮這個信息。

2

如果在移動webkit上工作,Shiboe的解決方案將是一個很好的解決方案,但事實並非如此。我能想出是一個mouseMove事件偵聽器的時候加入一些DOM對象,文件輸入窗口被打開,像這樣:

$('.upload-progress').mousemove(function() { 
     checkForFiles(this); 
     }); 
     checkForFiles = function(me) { 
     var filefield = $('#myfileinput'); 
     var files = filefield.get(0).files; 
     if (files == undefined || files[0] == undefined) $(me).remove(); // user cancelled the upload 
     }; 

從頁面阻止鼠標移動事件,而文件對話框是打開的,當它關閉時,檢查文件輸入中是否有文件。在我的情況下,我想要一個活動指示器來阻止文件上傳,所以我只想在取消時刪除我的指示器。

但是這並不解決移動,因爲沒有鼠標移動。我的解決方案不夠完美,但我認爲它足夠好。

 $('.upload-progress').bind('touchstart', function() { 
     checkForFiles(this); 
     }); 

現在我們正在監聽屏幕上的文字,以執行相同的文件檢查。我非常有信心,取消後用戶的手指會很快放到屏幕上,並關閉此活動指示器。

也可以在文件輸入更改事件上添加活動指示符,但在移動設備上,選擇圖像和更改事件觸發之間通常會有幾秒的時滯,所以它的活動指示器的UX更好,在過程開始時顯示。

5

只聽點擊事件。

從Shiboe的例子之後,這裏有一個jQuery的例子:

var godzilla = $('#godzilla'); 
var godzillaBtn = $('#godzilla-btn'); 

godzillaBtn.on('click', function(){ 
    godzilla.trigger('click'); 
}); 

godzilla.on('change click', function(){ 

    if (godzilla.val() != '') { 
     $('#state').html('You have chosen a Mech!');  
    } else { 
     $('#state').html('Choose your Mech!'); 
    } 

}); 

你可以看到它在這裏的行動:http://jsfiddle.net/T3Vwz

1

結合Shiboe的和ALX的解決方案,我已經得到了最可靠的代碼:

var selector = $('<input/>') 
    .attr({ /* just for example, use your own attributes */ 
     "id": "FilesSelector", 
     "name": "File", 
     "type": "file", 
     "contentEditable": "false" /* if you "click" on input via label, this prevents IE7-8 from just setting caret into file input's text filed*/ 
    }) 
    .on("click.filesSelector", function() { 
     /* do some magic here, e.g. invoke callback for selection begin */ 
     var cancelled = false; /* need this because .one calls handler once for each event type */ 
     setTimeout(function() { 
     $(document).one("mousemove.filesSelector focusin.filesSelector", function() { 
      /* namespace is optional */ 
      if (selector.val().length === 0 && !cancelled) { 
       cancelled = true; /* prevent double cancel */ 
       /* that's the point of cancel, */ 
      } 
     });      
     }, 1); /* 1 is enough as we just need to delay until first available tick */ 
    }) 
    .on("change.filesSelector", function() { 
     /* do some magic here, e.g. invoke callback for successful selection */ 
    }) 
    .appendTo(yourHolder).end(); /* just for example */ 

一般情況下,鼠標移動事件是卓有成效的,但如果用戶進行了點擊和比:

  • 取消打開文件對話框通過ESC鍵(不移動鼠標),另一個做準確的點擊打開文件對話框,再次...
  • 切換焦點任何其他應用程序,不是回來到瀏覽器的文件打開對話框,關閉它,再次通過輸入或空格鍵打開...

...我們不會得到mousemove事件,因此不會取消回調。而且,如果用戶取消第二個對話框並使鼠標移動,我們將獲得2個取消回調。 幸運的是,在這兩種情況下,特殊的jQuery focusIn事件都會影響文檔,幫助我們避免這種情況。唯一的限制是如果你阻止focusIn事件。

-3

我需要這樣做,我最終創建了一個非常簡單的解決方案。在這裏可以看到:http://jsfiddle.net/elizeubh2006/1w711q0y/5/

(但是隻會在第一個文件選擇發生後才起作用,對我來說這很有用,因爲即使用戶點擊取消,onchange事件也被調用,用戶選擇了一個文件,然後點擊選擇其他文件,但取消,平變化被調用。)

$("#inputFileId").on("change", function() { 
var x = document.getElementById('inputFileId'); 
    if(x.files.length == 0) 
    { 
    alert('cancel was pressed'); 
    } 
    else 
    { 
     alert(x.files[0].name); 
    } 

}); 
1

我看到我的反應會是較爲陳舊,但從來沒有少。 我面臨同樣的問題。所以這是我的解決方案。 最有用的代碼是KGA的。但它並不完全有效,而且有點複雜。但我簡化了它。

而且,主要的麻煩製造者是事實,「變」事件不聚焦後立即過來,所以我們必須等待一段時間。

「#appendfile」 - 哪個用戶點擊附加一個新文件。 Hrefs獲得焦點事件。

$("#appendfile").one("focusin", function() { 
    // no matter - user uploaded file or canceled, 
    // appendfile gets focus 
    // change doesn't come instantly after focus, so we have to wait for some time 
    // wrapper represents an element where a new file input is placed into 
    setTimeout(function(){ 
     if (wrapper.find("input.fileinput").val() != "") { 
      // user has uploaded some file 
      // add your logic for new file here 
     } 
     else { 
      // user canceled file upload 
      // you have to remove a fileinput element from DOM 
     } 
    }, 900); 
}); 
1

您只能在有限的情況下檢測到此情況。具體來說,如果先前選擇了文件,然後點擊文件對話框並單擊取消,Chrome會清除該文件並觸發onChange事件。

https://code.google.com/p/chromium/issues/detail?id=2508

在這種情況下,你可以通過處理onChange事件和檢查文件屬性來檢測這一點。

6
/* Tested on Google Chrome */ 
$("input[type=file]").bind("change", function() { 
    var selected_file_name = $(this).val(); 
    if (selected_file_name.length > 0) { 
     /* Some file selected */ 
    } 
    else { 
     /* No file selected or cancel/close 
      dialog button clicked */ 
     /* If user has select a file before, 
      when they submit, it will treated as 
      no file selected */ 
    } 
}); 
2

大多數這些解決方案不適用於我。

問題是你永遠不知道哪個事件會引發拳頭, 是click還是change?你不能假設任何順序,因爲它可能取決於瀏覽器的實現。

至少在Opera和Chrome(2015年底)click只是「填補」與文件輸入,所以你永遠不會知道的files.length != 0長度,直到你延遲clickchange後觸發之前觸發。

這裏是代碼:

var inputfile = $("#yourid"); 

inputfile.on("change click", function(ev){ 
    if (ev.originalEvent != null){ 
     console.log("OK clicked"); 
    } 
    document.body.onfocus = function(){ 
     document.body.onfocus = null; 
     setTimeout(function(){ 
      if (inputfile.val().length === 0) console.log("Cancel clicked"); 
     }, 1000); 
    }; 
}); 
-3

INPUT TYPE =文件代碼:

onchange="if(this.files[0]!=undefined){ UploadImg(); }else{ alert('cancel'); }" 
-2

您可以在輸入域jQuery的變化監聽並檢測用戶取消或關閉的上傳窗口該字段的值。

這裏有一個例子:

//when upload button change 
$('#upload_btn').change(function(){ 
    //get uploaded file 
    var file = this.files[0]; 

    //if user choosed a file 
    if(file){ 
     //upload file or perform your desired functiuonality 
    }else{ 
     //user click cancel or close the upload window 
    } 
}); 
0

這裏是我的解決方案,使用文件輸入焦點(不使用任何計時器)

var fileInputSelectionInitiated = false; 
 

 
function fileInputAnimationStart() { 
 
    fileInputSelectionInitiated = true; 
 
    if (!$("#image-selector-area-icon").hasClass("fa-spin")) 
 
     $("#image-selector-area-icon").addClass("fa-spin"); 
 
    if (!$("#image-selector-button-icon").hasClass("fa-spin")) 
 
     $("#image-selector-button-icon").addClass("fa-spin"); 
 
} 
 

 
function fileInputAnimationStop() { 
 
    fileInputSelectionInitiated = false; 
 
    if ($("#image-selector-area-icon").hasClass("fa-spin")) 
 
     $("#image-selector-area-icon").removeClass("fa-spin"); 
 
    if ($("#image-selector-button-icon").hasClass("fa-spin")) 
 
     $("#image-selector-button-icon").removeClass("fa-spin"); 
 
} 
 

 
$("#image-selector-area-wrapper").click(function (e) { 
 
    $("#fileinput").focus(); 
 
    $("#fileinput").click(); 
 
}); 
 

 
$("#preview-image-wrapper").click(function (e) { 
 
    $("#fileinput").focus(); 
 
    $("#fileinput").click(); 
 
}); 
 

 
$("#fileinput").click(function (e) { 
 
    fileInputAnimationStart(); 
 
}); 
 

 
$("#fileinput").focus(function (e) { 
 
    fileInputAnimationStop(); 
 
}); 
 

 
$("#fileinput").change(function(e) { 
 
    // ... 
 
}

0

這是哈克充其量,我的解決方案的but here is a working example檢測用戶是否上傳了文件,並且只允許他們在上傳文件時繼續即

基本上隱藏了Continue,Save,Proceed或任何你的按鈕。然後在JavaScript中抓取文件名。如果文件名沒有值,則不要顯示Continue按鈕。如果它有一個值,則顯示該按鈕。如果他們第一次上傳文件,然後他們嘗試上傳不同的文件並點擊取消,這也起作用。

這是代碼。

HTML:

<div class="container"> 
<div class="row"> 
    <input class="file-input" type="file" accept="image/*" name="fileUpload" id="fileUpload" capture="camera"> 
    <label for="fileUpload" id="file-upload-btn">Capture or Upload Photo</label> 
</div> 
<div class="row padding-top-two-em"> 
    <input class="btn btn-success hidden" id="accept-btn" type="submit" value="Accept & Continue"/> 
    <button class="btn btn-danger">Back</button> 
</div></div> 

的JavaScript:

$('#fileUpload').change(function() { 
    var fileName = $('#fileUpload').val(); 
    if (fileName != "") { 
     $('#file-upload-btn').html(fileName); 
     $('#accept-btn').removeClass('hidden').addClass('show'); 
    } else { 
     $('#file-upload-btn').html("Upload File"); 
     $('#accept-btn').addClass('hidden'); 
    } 
}); 

CSS:

.file-input { 
    width: 0.1px; 
    height: 0.1px; 
    opacity: 0; 
    overflow: hidden; 
    position: absolute; 
    z-index: -1; 
} 

.file-input + label { 
    font-size: 1.25em; 
    font-weight: normal; 
    color: white; 
    background-color: blue; 
    display: inline-block; 
    padding: 5px; 
} 

.file-input:focus + label, 
.file-input + label:hover { 
    background-color: red; 
} 

.file-input + label { 
    cursor: pointer; 
} 

.file-input + label * { 
    pointer-events: none; 
} 

對於CSS了很多,這是使網站和按鈕爲大家訪問。將你的按鈕設置爲任何你喜歡的。

0

下,似乎爲我工作(在桌面上,窗口):

var openFile = function (mimeType, fileExtension) { 
    var defer = $q.defer(); 
    var uploadInput = document.createElement("input"); 
    uploadInput.type = 'file'; 
    uploadInput.accept = '.' + fileExtension + ',' + mimeType; 

    var hasActivated = false; 

    var hasChangedBeenCalled = false; 
    var hasFocusBeenCalled = false; 
    var focusCallback = function() { 
     if (hasActivated) { 
      hasFocusBeenCalled = true; 
      document.removeEventListener('focus', focusCallback, true); 
      setTimeout(function() { 
       if (!hasChangedBeenCalled) { 
        uploadInput.removeEventListener('change', changedCallback, true); 
        defer.resolve(null); 
       } 
      }, 300); 
     } 
    }; 

    var changedCallback = function() { 
     uploadInput.removeEventListener('change', changedCallback, true); 
     if (!hasFocusBeenCalled) { 
      document.removeEventListener('focus', focusCallback, true); 
     } 
     hasChangedBeenCalled = true; 
     if (uploadInput.files.length === 1) { 
      //File picked 
      var reader = new FileReader(); 
      reader.onload = function (e) { 
       defer.resolve(e.target.result); 
      }; 
      reader.readAsText(uploadInput.files[0]); 
     } 
     else { 
      defer.resolve(null); 
     } 
    }; 
    document.addEventListener('focus', focusCallback, true); //Detect cancel 
    uploadInput.addEventListener('change', changedCallback, true); //Detect when a file is picked 
    uploadInput.click(); 
    hasActivated = true; 
    return defer.promise; 
} 

這確實使用angularjs $ Q,但你應該能夠在需要時與任何其他的承諾框架來取代它。

測試IE11,Edge,Chrome,Firefox,但它似乎不適用於Android平板電腦上的Chrome,因爲它不會觸發Focus事件。

-1

我發現了這個屬性,它最簡單了。

if ($('#selectedFile')[0].files.length > 1) 
{ 
    // Clicked on 'open' with file 
} else { 
    // Clicked on 'cancel' 
} 

這裏,selectedFileinput type=file

0

file-type字段令人沮喪地不響應大量事件(模糊會很可愛)。我看到很多人建議以change爲導向的解決方案,並讓他們陷入低調。

change確實有效,但它有一個主要缺陷(vs我們想要發生)。

當您剛剛加載包含文件字段的頁面時,請打開該框並按取消。沒有什麼,令人沮喪的是,變化

我選擇做的是加載門控狀態。

  • 在我的情況下,形式爲section#after-image的下一部分是隱藏的視圖。當我的file field更改時,會顯示一個上傳按鈕。成功上傳後,顯示section#after-image
  • 如果用戶加載,打開文件對話框,然後取消,他們永遠不會看到上傳按鈕。
  • 如果用戶選擇一個文件,則會顯示上傳按鈕。如果他們然後打開對話框並取消,則該取消觸發change事件,並且我可以(並且確實)重新隱藏我的上傳按鈕,直到選擇了正確的文件。

我很幸運,這門控狀態已經是我的形式的設計。您不需要使用相同的樣式,只需將上傳按鈕隱藏起來,並在更改時將隱藏字段或JavaScript變量設置爲您可以在提交時監控的內容。

我試圖在字段交互之前更改文件[0]的值。這對onchange沒有任何幫助。

所以是的,change的作品,至少和我們一樣好。由於顯而易見的原因,filefield是安全的,但對於善意開發人員的挫敗感。

這不符合我的目的,但您可能會加載一個警告提示(不是alert(),因爲它阻止了頁面處理),並且如果觸發更改並且文件[0]爲空值。如果更改未觸發,則div保持其狀態。

0

嗯,這並不完全回答你的問題。我的假設是,你有一個場景,當你添加一個文件輸入,並調用文件選擇,如果用戶點擊取消,你只需刪除輸入。

如果是這樣的話,那麼:爲什麼要添加空文件輸入?

即時創建一個,但把它添加到DOM只有當它填充像這樣:

var fileInput = $("<input type='file' name='files' style='display: none' />"); 
    fileInput.bind("change", function() { 
     if (fileInput.val() !== null) { 
      // if has value add it to DOM 
      $("#files").append(fileInput); 
     } 
    }).click(); 

所以我在這裏創建<輸入類型=「文件」上飛/ >,綁定到它的更改事件,然後立即調用點擊。只有當用戶選擇文件並點擊確定時,更改纔會觸發,否則輸入不會被添加到DOM,因此不會被提交。

工作示例這裏:https://jsfiddle.net/69g0Lxno/3/

0

最簡單的方法是檢查是否有臨時存儲的任何文件:)如果你想更改事件每次用戶點擊該文件輸入,您可以觸發它:)我希望這有助於;)

var yourFileInput = $("#yourFileInput"); 

yourFileInput.on('mouseup', function() { 
    $(this).trigger("change"); 
}).on('change', function() { 
    if (this.files.length) { 
     //User chose a picture 
    } else { 
     //User clicked cancel 
    } 
}); 

問候,KJ

0

//使用懸停,而不是模糊

var fileInput = $("#fileInput"); 

if (fileInput.is(":hover") { 

    //open 
} else { 

} 
相關問題