如何在Firefox 3中从HTMLinput表单获取文件path

我们使用<input type="file">简单的HTML表单,如下所示:

 <form> <label for="attachment">Attachment:</label> <input type="file" name="attachment" id="attachment"> <input type="submit"> </form> 

在IE7(也许所有着名的浏览器,包括旧的Firefox 2),如果我们提交一个像“// server1 / path / to / file / filename”这样的文件,它可以正常工作,并提供文件和文件名的完整path。

在Firefox 3中,由于其新的“安全function”来截断path,所以它只返回“文件名”,正如Firefox错误跟踪系统( https://bugzilla.mozilla.org/show_bug.cgi?id=143220 )

我不知道如何克服这个“新function”,因为它导致我的web应用程序中的所有上传表单停止在Firefox 3上工作。

任何人都可以帮助find一个单一的解决scheme,以获得在Firefox 3和IE7的文件path?

在IE7(也许所有着名的浏览器,包括旧的Firefox 2),如果我们提交一个像“// server1 / path / to / file / filename”这样的文件,它可以正常工作,并提供文件和文件名的完整path。

我不知道如何克服这个“新function”,因为它导致我的web应用程序中的所有上传表单停止在Firefox 3上工作。

这里有一个重大的误解。 为什么你需要在服务器端的完整文件path? 想象一下,我是客户端,我在C:\path\to\passwords.txt有一个文件,我给你完整的文件path。 作为服务器,你将如何获得其内容 ? 你有一个开放的TCP连接到我的本地磁盘文件系统? 当您在不同的服务器机器上将Web应用程序投入生产时,是否testing了file uploadfunction?

只有当客户端和服务器在物理上相同的机器上运行时,它才会起作用,因为这样你就可以访问同一个硬盘文件系统。 这只会在您本地开发您的网站时发生,因此,浏览器(客户端)和networking服务器(服务器)在同一台机器上运行。

在MSIE和其他古代浏览器发送完整的文件path是由于一个安全漏洞 。 W3和RFC2388规范从未提及包含完整的文件path。 只有文件名。 Firefox正在正确地完成它的工作。

要处理上传的文件,你不需要知道完整的文件path。 在multipart/form-data请求的情况下,您应该对客户端已经发送到请求主体中的服务器的完整文件内容感兴趣。 如RFC2388中所述,将表单更改为如下所示:

 <form action="upload-script-url" method="post" enctype="multipart/form-data"> <input type="file" name="file"> <input type="submit"> </form> 

如何获取服务器端上传文件的内容取决于您使用的服务器端编程语言。

  • Java / JSP :您想使用HttpServletRequest#getPart()或Apache Commons FileUpload API来parsing它。 您最终将得到一个InputStream文件内容,您可以根据自己的口味写入任何OutputStream文件。 你可以在这个答案中find一个例子。

  • Java / JSF :你想要使用<h:inputFile>组件或其他由你使用的组件库提供的file upload组件。 在这里,你也想获得InputStream风格的文件内容。 看到这个答案的例子。

  • PHP :文件内容已经隐式存储在临时磁盘上。 你想使用move_uploaded_file()函数将其移动到所需的位置。 另请参阅PHP手册 。

  • ASP.NET :没有详细的答案,因为我不这样做,但是Google为我find了一些示例: ASP.NET示例 , ASP.NET 2.0示例

无论何时您想要获取上传文件的文件名部分,都应该修剪文件名中的完整path。 这些信息与你完全无关。 另请参阅此Apache Commons FileUpload FAQ条目

为什么FileItem.getName()返回整个path,而不仅仅是文件名?

Internet Explorer提供了上传文件的完整path,而不仅仅是基本文件名。 由于FileUpload完全提供了客户端(浏览器)提供的内容,因此您可能希望在应用程序中删除此path信息。

在Firefox中预览的作品 – 附件是第一个例子中附件元素的对象:

  if (attachment.files) previewImage.src = attachment.files.item(0).getAsDataURL(); else previewImage.src = attachment.value; 

实际上,在FF3出来之前,我做了一些实验,FF2只发送文件名,就像Opera 9.0一样。 只有IE发送完整的path。 这种行为是有道理的,因为服务器不必知道用户在他的计算机上存储文件的位置,这与上传过程无关。 除非你正在编写一个intranet应用程序,并通过直接的networking访问获取文件!

什么改变了(这就是你指向的bug项目的真正意义)是FF3不再允许从JavaScript访问文件path。 并且不会在那里键入/粘贴一个path,这对我来说更加恼人:我有一个shell扩展,它将文件的path从Windows资源pipe理器复制到剪贴板,我在这种forms中使用了很多。 我通过使用DragDropUpload扩展来解决这个问题。 但是,我担心这个话题会变得无关紧要。

我不知道你的Web表单正在做什么来停止使用这种新的行为。

[编辑]在阅读由Mike链接的页面后,我确实看到了内部网使用path(例如标识用户)和本地使用(显示图像的预览,文件的本地pipe理)。 用户Jam-es似乎提供了nsIDOMFile(尚未尝试)的解决方法。

我们无法在FF3中获得完整的文件path。 以下可能对文件组件自定义有用。

 <script> function setFileName() { var file1=document.forms[0].firstAttachmentFileName.value; initFileUploads('firstFile1','fileinputs1',file1); } function initFileUploads(fileName,fileinputs,fileValue) { var fakeFileUpload = document.createElement('div'); fakeFileUpload.className = 'fakefile'; var filename = document.createElement('input'); filename.type='text'; filename.value=fileValue; filename.id=fileName; filename.title='Title'; fakeFileUpload.appendChild(filename); var image = document.createElement('input'); image.type='button'; image.value='Browse File'; image.size=5100; image.style.border=0; fakeFileUpload.appendChild(image); var x = document.getElementsByTagName('input'); for (var i=0; i&lt;x.length;i++) { if (x[i].type != 'file') continue; if (x[i].parentNode.className != fileinputs) continue; x[i].className = 'file hidden'; var clone = fakeFileUpload.cloneNode(true); x[i].parentNode.appendChild(clone); x[i].relatedElement = clone.getElementsByTagName('input')[0]; x[i].onchange= function () { this.relatedElement.value = this.value; }} if(document.forms[0].firstFile != null && document.getElementById('firstFile1') != null) { document.getElementById('firstFile1').value= document.forms[0].firstFile.value; document.forms[0].firstAttachmentFileName.title=document.forms[0].firstFile.value; } } function submitFile() { alert( document.forms[0].firstAttachmentFileName.value); } </script> <style>div.fileinputs1 {position: relative;}div.fileinputs2 {position: relative;} div.fakefile {position: absolute;top: 0px;left: 0px;z-index: 1;} input.file {position: relative;text-align: right;-moz-opacity:0 ;filter:alpha(opacity: 0); opacity: 0;z-index: 2;}</style> <html> <body onLoad ="setFileName();"> <form> <div class="fileinputs1"> <INPUT TYPE=file NAME="firstAttachmentFileName" styleClass="file" /> </div> <INPUT type="button" value="submit" onclick="submitFile();" /> </form> </body> </html> 

解决这个问题的一个非常难看的方法是让用户手动将目录input到文本框中,然后将其添加回JavaScript中文件值的前面。

凌乱…但这取决于你正在使用的用户的水平,并绕过安全问题。

 <form> <input type="text" id="file_path" value="C:/" /> <input type="file" id="file_name" /> <input type="button" onclick="ajax_restore();" value="Restore Database" /> </form> 

JavaScript的

 var str = document.getElementById('file_path').value; var str = str + document.getElementById('file_name').value; 

只是你不能用FF3做到这一点。

另一个选项可能是使用小程序或其他控件来select和上传文件。

看看XPCOM ,如果客户端使用Firefox 3,可能会有一些可以使用的东西。

这是一个备用解决scheme/修复…在FF3中,您可以检索文件的文件的完整path而不是文件浏览框。 那也是…通过拖放文件!

你可以拖放你的文件到你的HTML页面的文本框中。 它会显示文件的完整path。 这些数据可以很容易地转移到你的服务器上或者操纵它们。

你所要做的就是使用扩展DragDropUpload

http://www.teslacore.it/wiki/index.php?title=DragDropUpload

该扩展将帮助您将文件拖放到“文件浏览”(input文件)框中。 但是你仍然无法获得文件的完整path,如果你尝试检索。

所以,我稍微调整了这个扩展。 以这种方式,我可以拖放一个文件到任何“文本input”框,并获得文件的完整path。 因此,我可以在FF3 Firefox 3中获得文件的完整path。

如果你需要的不是完全的path,而是离线工作的文件的引用,这是一个可以为你工作的例子。

http://www.ab-d.fr/date/2008-07-12/

这是在法国,但代码是JavaScript 🙂

这是文章指出的参考: http : //developer.mozilla.org/en/nsIDOMFile http://developer.mozilla.org/en/nsIDOMFileList