我们有<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'这样的文件,它可以正常工作并提供完整路径 文件和文件名。
在Firefox 3中,它只返回'filename',因为它们用于截断路径的新“安全功能”,如Firefox错误跟踪系统(https://bugzilla.mozilla.org/show_bug.cgi?id=143220)中所述
我不知道如何克服这个'新功能',因为它会导致我的webapp中的所有上传表单停止在Firefox 3上运行。
任何人都可以帮助找到一个解决方案来获取Firefox 3和IE7上的文件路径吗?
答案 0 :(得分:60)
在IE7(可能是所有着名的浏览器,包括旧的Firefox 2)中,如果我们提交像'// server1 / path / to / file / filename'这样的文件,它可以正常工作并提供文件的完整路径和文件名。
我不知道如何克服这个'新功能',因为它会导致我的webapp中的所有上传表单停止在Firefox 3上运行。
这里有一个重大的误解。为什么在服务器端需要完整的文件路径?想象一下,我是客户端,我在C:\path\to\passwords.txt
有一个文件,我给你完整的文件路径。作为服务器,您将如何获得内容?您是否有与本地磁盘文件系统的开放TCP连接?在将Web应用程序投入到其他服务器计算机的生产中时,您是否测试了文件上载功能?
仅当两者客户端和服务器在物理上相同的计算机上运行时才会起作用,因为您将可以访问相同的硬盘文件系统。这只会在您在本地开发您的网站时发生,因此巧合的webbrowser(客户端)和Web服务器(服务器)都在同一台机器上运行。
在MSIE和其他古老的网络浏览器中发送完整文件路径是由于安全漏洞。 W3和RFC2388规范从未提及包含完整文件路径。只有文件名。 Firefox正在正常工作。
要处理上传的文件,您不需要知道完整的文件路径。在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来解析它。你最终应该得到InputStream
文件内容,然后你可以根据自己的喜好写入OutputStream
。您可以在this answer。
Java / JSF :您希望使用<h:inputFile>
组件或您正在使用的组件库提供的任何其他文件上传组件。此外,您还想获得InputStream
风格的文件内容。有关示例,请参阅this answer。
PHP :文件内容已隐式存储在临时磁盘上。您想使用move_uploaded_file()
功能将其移动到所需位置。另请参阅PHP manual。
ASP.NET :由于我不这样做,所以没有我的详细答案,但Google已经为我找到了一些示例:ASP.NET example,ASP.NET 2.0 example
每当您想要获取上传文件的文件名部分时,您应该修剪文件名中的完整路径。这些信息与您完全无关。另请参阅此示例Apache Commons FileUpload FAQ entry
为什么FileItem.getName()返回整个路径,而不仅仅是文件名?
Internet Explorer提供上传文件的完整路径,而不仅仅是基本文件名。由于FileUpload完全提供客户端(浏览器)提供的内容,因此您可能希望在应用程序中删除此路径信息。
答案 1 :(得分:10)
对于Firefox中的预览工作原理 - 附件是第一个示例中的附件元素的对象:
if (attachment.files)
previewImage.src = attachment.files.item(0).getAsDataURL();
else
previewImage.src = attachment.value;
答案 2 :(得分:2)
实际上,就在FF3出局之前,我做了一些实验,而FF2只发送了文件名,就像Opera 9.0一样。只有IE发送完整路径。这种行为是有道理的,因为服务器不必知道用户在其计算机上存储文件的位置,这与上载过程无关。除非您正在编写Intranet应用程序并通过直接网络访问获取文件!
改变了什么(这是你指出的错误项目的真正意义)是FF3不再允许从JavaScript访问文件路径。并且不会在那里输入/粘贴路径,这对我来说更烦人:我有一个shell扩展,它将文件的路径从Windows资源管理器复制到剪贴板,我在这种形式中使用了很多。我通过使用DragDropUpload扩展解决了这个问题。但是我担心这会成为偏离主题的。
我想知道您的Web表单正在做些什么来停止使用这种新行为。
[编辑]阅读Mike链接的页面后,我确实看到内部网使用路径(例如识别用户)和本地使用(显示图像预览,文件的本地管理)。用户Jam-es似乎提供了nsIDOMFile的解决方法(尚未尝试)。
答案 3 :(得分:2)
我们无法在FF3中获得完整的文件路径。以下内容可能对文件组件自定义很有用。
<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<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>
答案 4 :(得分:0)
只是你无法用FF3做到这一点。
另一个选项可能是使用applet或其他控件来选择和上传文件。
答案 5 :(得分:0)
看一下XPCOM,如果客户端使用Firefox 3,可能会有一些东西可供使用。
答案 6 :(得分:0)
如果您需要的不完全是路径,而是对脱机工作文件的引用,这个示例可能对您有用。
http://www.ab-d.fr/date/2008-07-12/
它是法语,但代码是javascript:)
这是文章指出的参考资料: http://developer.mozilla.org/en/nsIDOMFile http://developer.mozilla.org/en/nsIDOMFileList
答案 7 :(得分:0)
这是一个替代解决方案/修复...在FF3中,您可以在文本框中检索文件的完整路径,而不是文件浏览框。那也是......通过拖放文件!
您可以将文件拖放到html页面的文本框中。它将显示文件的完整路径。这些数据可以很容易地传输到您的服务器或操纵它们。
您所要做的就是使用扩展名DragDropUpload
http://www.teslacore.it/wiki/index.php?title=DragDropUpload
此扩展程序可帮助您将文件拖放到文件浏览(输入文件)框中。但是你仍然无法获得文件的完整路径,如果你试图检索。
所以,我稍微调整了这个扩展名。在这种方式,我可以将文件拖放到任何“文本输入”框,并获取文件的完整路径。因此,我可以在FF3 Firefox 3中获得文件的完整路径。
答案 8 :(得分:0)
解决此问题的一种非常难看的方法是让用户手动将目录键入文本框,然后将其添加回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;