gpt4 book ai didi

javascript - 记住并重新填充文件输入

转载 作者:行者123 更新时间:2023-12-02 09:37:56 27 4
gpt4 key购买 nike

这个问题在这里已经有了答案:





How to set file input value when dropping file on page? [duplicate]

(1 个回答)


3年前关闭。




Note:

The answer(s) below reflect the state of legacy browsers in 2009. Now you can actually set the value of the file input element via JavaScript in 2017.

See the answer in this question for details as well as a demo:
How to set file input value programatically (i.e.: when drag-dropping files)?



我有一个网站,允许用户多次上传文件进行处理。目前我只有一个文件输入,但我希望能够记住用户的选择并将其显示在屏幕上。

我想知道如何做的是在用户选择一个文件后,我会记住他们的选择,并使用重新加载页面时预先选择的文件重新显示文件输入。我只需要知道如何记住和重新填充文件输入。

我也对不使用文件输入的方法持开放态度(如果可能的话)。

我正在使用 JQuery

最佳答案

好的,您想“记住并重新填充文件输入”,“记住他们的选择并使用重新加载页面时预先选择的文件重新显示文件输入”..
在对我之前的回答的评论中,您表示您对替代方案并不真正开放:“抱歉,没有 Flash 和小程序,只有 javscript 和/或文件输入,可能会拖放。”

我在浏览(相当多)重复问题时注意到( 123 等),几乎所有其他答案都在:“不,你不能遵循安全问题”,这是可选的通过一个简单的概念或代码示例概述安全风险。

然而,像骡子一样固执的人(在一定程度上不一定是坏事)可能会认为这些答案是:“不,因为我这么说”,这确实是不同的:“不,这里是规范禁止它”。
所以这是我第三次也是最后一次回答你的问题(我带你到水坑,我带你到河边,现在我推你到源头,但我不能让你喝)。

编辑 3:

您想要做的实际上曾经在 RFC1867 第 3.4 节中描述/“建议”:

The VALUE attribute might be used with <INPUT TYPE=file> tags for a default file name. This use is probably platform dependent. It might be useful, however, in sequences of more than one transaction, e.g., to avoid having the user prompted for the same file name over and over again.



事实上, HTML 4.01 spec section 17.4.1 指定:

User agents may use the value of the value attribute as the initial file name.



(“用户代理”是指“浏览器”)。

鉴于javascript可以修改和提交表单(包括文件输入)并且可以使用css隐藏表单/表单元素(如文件输入)的事实,仅上述语句就可以静默上传在用户无意/不知情的情况下从用户的计算机中获取文件。
显然这是不可能的,这一点非常重要,因此,(以上)RFC1867 在第 8 节安全注意事项中指出:

It is important that a user agent not send any file that the user has not explicitly asked to be sent. Thus, HTML interpreting agents are expected to confirm any default file names that might be suggested with <INPUT TYPE=file VALUE="yyyy">.



但是,唯一实现此功能的浏览器(我知道)是(某些旧版本)Opera:它接受 <input type="file" value="C:\foo\bar.txt> 或由 javascript 设置的值( elm_input_file.value='c:\\foo\\bar.txt'; )。
当这个文件框在表单提交时没有改变时,Opera 会弹出一个安全窗口,通知用户什么文件要上传到什么位置(url/网络服务器)。

现在人们可能会争辩说所有其他浏览器都违反了规范,但这是错误的:因为规范声明:“ may ”(它没有说“ must ”)“..使用值属性作为初始文件名” .
而且,如果浏览器不接受设置文件输入值(也就是将该值设为“只读”),那么浏览器也不需要弹出这样一个“可怕”和“困难”的安全性-pop-up(如果用户不理解它(和/或“有条件”总是单击“确定”),则它甚至可能无法达到其目的)。

让我们快进到 HTML 5 然后..
在这里,所有这些歧义都被清除了(但它仍然需要一些令人费解):

4.10.7.1.18 File Upload state 下,我们可以阅读簿记详细信息:

  • The value IDL attribute is in mode filename.
    ...
  • The element's value attribute must be omitted.


因此,必须省略文件输入的 value 属性,但它也以某种称为“文件名”的“模式”运行,在 4.10.7.4 Common input element APIs 中描述:

The value IDL attribute allows scripts to manipulate the value of an input element. The attribute is in one of the following modes, which define its behavior:



跳到这个“ mode filename”:

On getting, it must return the string "C:\fakepath\" followed by the filename of the first file in the list of selected files, if any, or the empty string if the list is empty. On setting, if the new value is the empty string, it must empty the list of selected files; otherwise, it must throw an InvalidStateError exception.



让我重复一遍:“它 must 抛出一个 InvalidStateError 异常”如果有人试图将文件输入值设置为非空字符串!!! (但可以通过将其值设置为空字符串来清除输入字段。)

因此,目前和在可预见的 HTML5 future (以及过去,Opera 除外)、 只有用户可以通过 0x2518411921 浏览器填充文件输入(0x2518411921 os1-files'-files'-files'-files'-files'- 不能(重新)使用 javascript 或通过设置默认值将文件输入填充到文件/目录。

获取文件名/文件路径

现在,假设使用默认值(重新)填充文件输入并非不可能,那么显然您需要完整路径:目录+文件名(+扩展名)。

过去,一些浏览器(最显着的)IE6(直到 IE8)确实显示完整路径+文件名作为值:只是一个简单的 alert( elm_input_file.value ); 等 javascript 并且浏览器也发送了这个完整路径+文件名(+扩展名)到表单提交上的接收服务器。
注意:一些浏览器也有一个“文件或文件名”属性(通常发送到服务器)但显然这不会包括路径..

这是一个现实的安全/隐私风险:恶意网站(所有者/利用者)可以获得用户主目录的路径(个人资料、帐户、cookies、注册表的用户部分、历史记录、收藏夹、桌面等)位于已知的固定位置),当典型的非技术 Windows 用户将上传他的文件时: C:\Documents and Settings\[UserName]\My Documents\My Pictures\kinky_stuff\image.ext
我什至没有谈论传输数据(甚至通过 https 进行“加密”)或“安全”存储这些数据时的风险!

因此,越来越多的替代浏览器开始遵循最古老的安全措施之一:在需要知道的基础上共享信息。
而且绝大多数网站不需要知道文件路径,所以他们只显示文件名(+扩展名)。

到 IE8 发布时,MS 决定跟上竞争,并添加了一个 URLAction 选项,称为“上传文件时包括本地目录路径”,该选项对于一般 Internet 区域设置为“禁用”(在常规 Internet 区域中设置为“启用”)受信任区域)默认情况下。

此更改造成了一个小破坏(主要是在“为 IE 优化”环境中),其中各种自定义代码和专有“控件”都无法获取上传文件的文件名:它们被硬编码为期望包含一个完整的路径并提取最后一个反斜杠之后的部分(如果幸运的话,或者正斜杠......)。 1, 2

随之而来的是 HTML5,
正如您在上面阅读的那样,“模式文件名”指定:

On getting, it must return the string "C:\fakepath\" followed by the filename of the first file in the list of selected files, if any, or the empty string if the list is empty.



他们注意到

This "fakepath" requirement is a sad accident of history





For historical reasons, the value IDL attribute prefixes the filename with the string "C:\fakepath\". Some legacy user agents actually included the full path (which was a security vulnerability). As a result of this, obtaining the filename from the value IDL attribute in a backwards-compatible way is non-trivial. The following function extracts the filename in a suitably compatible manner:

function extractFilename(path) {
if (path.substr(0, 12) == "C:\\fakepath\\")
return path.substr(12); // modern browser
var x;
x = path.lastIndexOf('/');
if (x >= 0) // Unix-based path
return path.substr(x+1);
x = path.lastIndexOf('\\');
if (x >= 0) // Windows-based path
return path.substr(x+1);
return path; // just the filename
}


注意:我认为这个函数很愚蠢:重点是总是有一个假的 windows-path 来解析..所以第一个 'if' 不仅没用,而且甚至会引发一个错误:想象一个用户使用旧浏览器上传来自: c:\fakepath\Some folder\file.ext 的文件(因为它会返回: Some folder\file.ext )...
我会简单地使用:
function extractFilename(s){ 
// returns string containing everything from the end of the string
// that is not a back/forward slash or an empty string on error
// so one can check if return_value===''
return (typeof s==='string' && (s=s.match(/[^\\\/]+$/)) && s[0]) || '';
}

(正如 HTML5 规范明确打算的那样)。

让我们回顾一下(获取路径/文件名):
  • 较旧的浏览器(以及可以将其作为选项启用的较新浏览器,例如 IE>=8)将显示完整的 windows/unix 路径
  • 较旧的浏览器不会显示任何路径,只是一个文件名(+扩展名)
  • 当前/ future /HTML5 兼容的浏览器将始终在获取文件输入值时将字符串:c:\fakepath\ 前置到文件名
    最重要的是,如果文件输入接受多个文件并且用户选择了多个文件,它们只会返回第一个文件名(来自“选定文件列表”)。

  • 因此,在最近的过去,当前和可预见的 HTML5 future ,人们通常只会获得文件名。

    这将我们带到了我们需要检查的最后一件事:这个“选定文件列表”/多个文件,这将我们带到了谜题的第三部分:

    (HTML5) 文件 API

    首先:“文件 API”不应与“File System API”混淆,这里是文件系统 API 的摘要:

    This specification defines an API to navigate file system hierarchies, and defines a means by which a user agent may expose sandboxed sections of a user's local filesystem to web applications. It builds on [FILE-WRITER-ED], which in turn built on [FILE-API-ED], each adding a different kind of functionality.



    “用户本地文件系统的沙盒部分”已经清楚地表明不能使用它来获取沙盒之外的用户文件(因此与问题无关,尽管可以将用户选择的文件复制到持久性本地存储并使用 AJAX 等重新上传该副本。用作上传失败时的“重试”。但它不会是指向可能在此期间发生更改的原始文件的指针)。
    更重要的是,只有 webkit(想想旧版本的 chrome)实现了这个特性,并且规范很可能不会继续存在,因为它 is no more actively maintained, the specification is abandonned for the moment as it didn't get any significant traction

    让我们继续'File API',
    它的摘要告诉我们:

    This specification provides an API for representing file objects in web applications, as well as programmatically selecting them and accessing their data. This includes:

    • A FileList interface, which represents an array of individually selected files from the underlying system. The user interface for selection can be invoked via <input type="file">, i.e. when the input element is in the File Upload state [HTML] .
    • A Blob interface, which represents immutable raw binary data, and allows access to ranges of bytes within the Blob object as a separate Blob.
    • A File interface, which includes readonly informational attributes about a file such as its name and the date of the last modification (on disk) of the file.
    • A FileReader interface, which provides methods to read a File or a Blob, and an event model to obtain the results of these reads.
    • A URL scheme for use with binary data such as files, so that they can be referenced within web applications.


    因此, FileList 可以由文件模式下的输入字段填充: <input type="file">
    这意味着以上所有关于 value-attribute 的内容仍然适用!

    当输入字段处于文件模式时,它会得到一个 read-only attribute files ,它是一个类似数组的 FileList object,它引用输入元素的用户选择的文件,并且可以被 FileList interface 访问
    我有没有提到 the files -attribute of the type FileList is read-only (File API section 5.2) ? :

    The HTMLInputElement interface [HTML] has a readonly attribute of type FileList...



    那么, 拖放 怎么样?

    来自 mdn-documentation - Selecting files using drag and drop

    The real magic happens in the drop() function:

    function drop(e) {
    e.stopPropagation();
    e.preventDefault();

    var dt = e.dataTransfer;
    var files = dt.files;

    handleFiles(files);
    }

    Here, we retrieve the dataTransfer field from the event, then pull the file list out of it, passing that to handleFiles(). From this point on, handling the files is the same whether the user used the input element or drag and drop.



    因此,(就像 input-field type="file"一样)事件的 dataTransfer 属性有一个类似数组的属性 files,它是一个类似数组的 FileList object 并且我们刚刚了解到 FileList9131141214124114141
    ..

    FileList 包含对用户选择(或放置在放置目标上)的文件的引用和一些属性。从 File API Section 7.2 File Attributes 我们可以读到:

    name

    The name of the file; on getting, this must return the name of the file as a string. There are numerous file name variations on different systems; this is merely the name of the file, without path information. On getting, if user agents cannot make this information available, they must return the empty string.

    lastModifiedDate

    The last modified date of the file. On getting, if user agents can make this information available, this must return a new Date[HTML] object initialized to the last modified date of the file. If the last modification date and time are not known, the attribute must return the current date and time as a Date object.



    并且有一个 size 属性:

    F.size is the same as the size of the fileBits Blob argument, which must be the immutable raw data of F.



    同样,没有路径,只有 只读 文件名。

    因此:
  • (elm_input||event.dataTransfer).files 给出了 FileList 对象。
  • (elm_input||event.dataTransfer).files.length 给出了文件的数量。
  • (elm_input||event.dataTransfer).files[0] 是选择的第一个文件。
  • (elm_input||event.dataTransfer).files[0].name 是选择的第一个文件的文件名
    (这是从输入类型="file"返回的 value)。

  • 这个“用于二进制数据(如文件)的 URL 方案,以便它们可以在 Web 应用程序中被引用”,它肯定可以保存对用户选择的文件的私有(private)引用?

    File API - A URL for Blob and File reference 我们可以了解到:

    This specification defines a scheme with URLs of the sort:
    blob:550e8400-e29b-41d4-a716-446655440000#aboutABBA.



    它们存储在 URL store(浏览器甚至应该有自己的迷你 HTTP 服务器,这样人们就可以在 css、img src 甚至 XMLHttpRequest 中使用这些 url。

    可以使用以下命令创建那些 Blob URL s:
  • var myBlobURL=window.URL.createFor(object); 返回一个 Blob URL,在第一次使用后会自动撤销。
  • var myBlobURL=window.URL.createObjectURL(object, flag_oneTimeOnly); 返回可重用的 Blob URL(除非 flag_oneTImeOnly 评估为真)并且可以用 0x251812143133 撤销。

  • 宾果游戏你可能会想......但是...... window.URL.revokeObjectURL(myBlobURL) 仅在 session 期间维护(因此它会在页面刷新时继续存在,因为它仍然是同一个 session )并且在卸载文档时丢失。

    MDN - Using object URLs :

    The object URL is a string identifying the File object. Each time you call window.URL.createObjectURL(), a unique object URL is created, even if you've created an object URL for that file already. Each of these must be released. While they are released automatically when the document is unloaded, if your page uses them dynamically, you should release them explicitly by calling window.URL.revokeObjectURL()



    这意味着,即使您将 URL Store 字符串存储在 cookie 或持久性本地存储中,该字符串在新 session 中也无用!

    这应该使我们完整循环并得出最终结论:
    无法(重新)填充输入字段或用户选择的文件 (不在浏览器沙盒“本地存储”区域中)。
    (除非你强制你的用户使用过时的 Opera 版本,或者强制你的用户使用 IE 和一些 activeX 编码/模块(实现自定义文件选择器)等)

    一些进一步的阅读:
    http://www.cs.tut.fi/~jkorpela/forms/file.html
    https://developer.mozilla.org/en-US/docs/Using_files_from_web_applications
    http://www.html5rocks.com/en/tutorials/file/filesystem/
    http://www.html5rocks.com/en/tutorials/file/dndfiles/
    http://caniuse.com/filereader
    JavaScript:权威指南 - David Flanagan,第 22 章:文件系统 API
    How to save the window.URL.createObjectURL() result for future use?
    How long does a Blob persist?
    How to resolve the C:\fakepath?

    关于javascript - 记住并重新填充文件输入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20537696/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com