在IE9中,当从onchange触发.click()时出现“SCRIPT5 Access is denied”错误

10
我们希望减少用户在我们网站上上传文件所需的步骤数量;因此,我们使用 jQuery 来打开并回传文件,使用以下标记(简化版):
<a onclick="$('#uplRegistrationImage').click();">
    Change profile picture
</a>

<!-- Hidden to keep the UI clean -->
<asp:FileUpload ID="uplRegistrationImage" 
                runat="server" 
                ClientIDMode="static"
                Style="display:none"
                onchange="$('#btnSubmitImage').click();"    />

<asp:Button runat="server" 
            ID="btnSubmitImage" 
            ClientIDMode="static" 
            Style="display:none" 
            OnClick="btnSubmitImage_OnClick" 
            UseSubmitBehavior="False" />

在 Firefox 和 Chrome 中,这个功能完全正常:当点击链接时打开文件对话框,并在选择文件后触发回发。

然而,在 IE9 中,文件上传已加载并且用户已选择文件之后,OnChange 不起作用,会出现 "SCRIPT5 Access is denied" 错误。我尝试了设置任意超时、设置间隔以检查是否给定了文件,但都无济于事。

有许多其他相关的问题,但似乎没有一个合适的答案(其中一个说将文件对话框设置为透明并悬停在按钮后面!)

有其他人解决了这个问题吗?还是必须为 IE 用户提供一个按钮?


<a> onclick 会打开文件对话框;asp:FileUpload 应该在选择文件时触发 postback。 - Luke Merrett
我在Safari中也遇到了同样的问题,所以我猜测IE9采取了相同的立场,即click()实际上需要用户点击,从安全角度来看,您可能能够理解。 - samazi
最终我改变了应用程序结构以抽象出相关部分。我只是将其用作快捷方式,我没有被绑定到代码后/回发应用程序结构。有一种方法可以直接从jQuery访问代码后方法,这可能对您有所帮助。我建议使用jQuery直接链接到您的代码后。您可以在http://encosia.com/using-jquery-to-directly-call-aspnet-ajax-page-methods/阅读此内容。 - samazi
@Click-Rex,我刚刚发现了这个链接:http://forums.asp.net/t/1573660.aspx/1,看起来你只需要使用asp:Button而不是<a>标签,就可以解决问题。 - samazi
你确定 $('#btnSubmitImage').click(); 是导致这个问题的原因吗? - n.podbielski
显示剩余4条评论
4个回答

13

出于安全原因,您试图做的事情是不可能的。IE9似乎不会让您以这种方式提交表单,除非它是由文件上传控件上的实际鼠标单击触发的。

举个例子,我能够使用您的代码在仅当我自己点击了Browse按钮时,在change句柄中进行提交。我甚至在$(document).ready方法中设置了轮询变量,该变量由change处理程序设置,指示应触发提交 - 这也无效。

解决此问题的方法似乎是:

  1. 以这种方式为控件设置样式,使其位于按钮后面。您在问题中提到了这一点,但是Romas在这里提供的答案(在JavaScript中,我可以使“click”事件以编程方式触发文件输入元素吗?)实际上有效(我已经在IE9、Chrome v23和FF v15中尝试过)。
  2. 使用基于Flash的方法(GMail就是这样做的)。我尝试了Uploadify演示,它似乎运行得非常好。

为文件上传设置样式:

http://www.quirksmode.org/dom/inputfile.html

http://www.shauninman.com/archive/2007/09/10/styling_file_inputs_with_css_and_the_dom

参考资料:

jQuery:模拟在Firefox中单击<input type="file"/>不起作用?

如何使用JavaScript触发IE9文件输入?

在IE8上获得“访问被拒绝”错误


1
完美的答案,谢谢Nick。我们最终使用了FineUploader和HTTP处理程序;通过编写更多的样板代码实现了大致相同的解决方案。 - Luke Merrett
奇怪,这个 jsfiddle 似乎证明了这个答案是错误的:http://jsfiddle.net/NkycS/27/ 文件输入点击是通过 JS 触发的,提交也是如此,在 IE9 中可以正常工作。不知道我是否漏掉了什么。 - RwwL
是的,我漏掉了一些东西:我的文件输入框上没有name属性。只要我添加一个,就会出现访问被拒绝的错误。http://jsfiddle.net/NkycS/32/ - RwwL

3

嘿,这个解决方案可行。 对于下载,我们应该使用MSBLOB。

$scope.getSingleInvoicePDF = function(invoiceNumberEntity) {
   var fileName = invoiceNumberEntity + ".pdf";
   var pdfDownload = document.createElement("a");
   document.body.appendChild(pdfDownload);

   AngularWebService.getFileWithSuffix("ezbillpdfget",invoiceNumberEntity,"pdf" ).then(function(returnedJSON) {
       var fileBlob = new Blob([returnedJSON.data], {type: 'application/pdf'});
       if (navigator.appVersion.toString().indexOf('.NET') > 0) { // for IE browser
           window.navigator.msSaveBlob(fileBlob, fileName);
       } else { // for other browsers
           var fileURL = window.URL.createObjectURL(fileBlob);
           pdfDownload.href = fileURL;
           pdfDownload.download = fileName;
           pdfDownload.click();      
       }
   });
};

2
这个解决方案看起来可能有效。您需要将其包装在<form>中,并在jquery更改处理程序中进行提交,可能需要使用__eventtarget或iframe或Web表单使用的其他内容在form_load中进行处理,但它允许您选择一个文件,并通过提交表单发送它。由于我没有在家里设置环境,因此无法测试它。

http://jsfiddle.net/axpLc/1/

<a onclick="$('#inputFile').click();">
    Change profile picture
</a>
<div id='divHide'>

    <input id='inputFile' type='file' />

</div>


$('#inputFile').change(function() { alert('ran'); });

#divHide { display:none; }

0

好的,就像SLC所说,你应该使用<Form>标签。

首先,你应该指示文件的数量;这应该由你的输入字段确定。第二步是将它们堆叠成一个数组。

<input type="file" class="upload" name="fileX[]"/>

然后创建一个循环;通过循环,它将自动基于当前输入字段进行确定。
 $("input[@type=file]:nth(" + n +")")

然后您会注意到每个选择的文件; 都会将输入名称替换为文件名。 这应该是通过jQuery提交多个文件的非常基本的方法。

如果您想要一个单独的项目:

$("input[@type=file]").change(function(){
   doIt(this, fileMax);
 });

这将创建一个 Div,其中包含找到的最大文件,并附加到onEvent。上面相应的代码也需要这些:
 var fileMax = 3;
 <input type="file" class="upload" name="fileX[]" />

这应该导航DOM父树;然后分别创建字段。这是一种方法;另一种方法是使用SLC上面看到的方法。有很多方法可以做到这一点;这只是取决于你想要多少jQuery来操作它?

希望这可以帮助你;如果我误解了你的问题,对不起。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接