14

我正在开发一个允许用户上传图像的应用程序(在 Node.js 中,与这种情况无关)。使用带有输入 (type="file") 字段的表单可以正常工作。

但是,我想要的是能够使用 HTML5 拖放来上传图像。据我所知,可以将图像拖动到客户端,并且图像缩略图显示在 div 中。但是,我确实需要一些帮助才能使文件上传正常工作。

问题是我想使用我现在正在使用的表单,并且(以某种方式)将文件的路径传递给输入字段,即流程将完全像现在一样工作,而不是通过浏览来选择文件我想通过拖放将其附加到输入字段。

在下面用于拖放的 js 代码中,拖放到客户端的文件存储在变量“file”中,我可以使用“file.name”、“file.type”和“file.size”与以前使用表单的方式完全相同。但是,我无法访问文件“路径”(file.path),这使得无法访问文件服务器端进行上传,就像我以前那样。

问题是,是否可以在将文件拖到客户端后将文件对象传递给输入字段,以便我可以单击“提交”并上传文件?如果是这样,如何做到这一点?

提前致谢!

保管箱以及我用于文件上传的表单:

<div id='upload'>
    <article>
        <div id='holder'>
            <p id='status'>File API and FileReader API not supported</p>
        </div>
    </article> 

    <form method='post' enctype='multipart/form-data' action='/file-upload'>
        <p>
            <input type='file' name='thumbnail'>
        </p>
        <p>
            <input type='submit'>
        </p>
    </form>
</div>

拖放代码:

uploadImage: function(){
    var holder = document.getElementById('holder'),
        state = document.getElementById('status');

    if (typeof window.FileReader === 'undefined') {
      state.className = 'fail';
    } else {
      state.className = 'success';
      state.innerHTML = 'File API & FileReader available';
    }

    holder.ondragover = function () { this.className = 'hover'; return false; };

    holder.ondragend = function () { this.className = ''; return false; };

    holder.ondrop = function (e) {
      this.className = '';
      e.preventDefault();

      var file = e.dataTransfer.files[0],
          reader = new FileReader();

      reader.onload = function (event) {
        holder.style.background = 'url(' + event.target.result + ') no-repeat center';
      };

      reader.readAsDataURL(file);

      return false;
    };
},
4

3 回答 3

8

您不能使用文件输入来添加文件数据。尽管如此,您可以做的(在其他技术中)是使用 base64(在使用readAsDataURL方法时,通过 reader.onload 事件作为event.target.result原生可用)编码数据并将其放入隐藏字段:

html

<article>
    <div id='holder'>
        <p id='status'>File API and FileReader API not supported</p>
    </div>
</article> 

<form method='post' enctype='multipart/form-data' action='/file-upload'>
        <input type='file' name='thumbnail' />
        <input type='hidden' name='base64data' />
        <input type='submit' formenctype='application/x-www-form-urlencoded' />
</form>

js

reader = new FileReader();
reader.onload = function (event) {
    document.getElementById('base64data').setAttribute('value', event.target.result);
};
reader.readAsDataURL(file);

从服务器端,您将能够从文件中获取 base64 编码数据,只需对其进行解码并根据需要使用它。

提交表单时,您还可以更改“enctype”属性(通过formenctype属性完成)并删除基本的 html 文件输入,因为数据将发布在文本字段中。

于 2012-10-07T23:44:30.960 回答
0

出于安全目的,不可能知道该字段的路径。通过拖放,您必须让它独立于主表单上传。看这里的例子:http ://www.sitepoint.com/html5-file-drag-and-drop/

于 2012-05-14T20:58:46.377 回答
0

我发现在后面的代码中访问时未设置 reader.onload 中设置的隐藏字段(请参阅@challet 的答案)。我正在使用 asp.net 和一个 WebForms 项目。要访问隐藏字段,我必须在字段名称前添加 MainContent_。aspx 代码如下


<asp:Content ID="Content3" ContentPlaceHolderID="MainContent" runat="server">
...
<script type="text/javascript">
    function dropHandler(ev) {
        alert("File(s) dropped");
        // Prevent default behavior (Prevent file from being opened)
        ev.preventDefault();
        //alert("Default prevented");
        if (ev.dataTransfer.items) {
            if (ev.dataTransfer.items.length > 1) {
                alert("Only single files can be dragged and dropped into Caption Pro Web");
                return;
            }
            // If dropped items aren't files, reject them
            if (ev.dataTransfer.items[0].kind === 'file') {
                var file = ev.dataTransfer.items[0].getAsFile();                    
                document.getElementById("MainContent_DroppedFileName").value = ev.dataTransfer.items[0].name
                reader = new FileReader();
                reader.onload = function (event) {
                    document.getElementById('MainContent_DroppedFileContent').value = event.target.result;
                };
                reader.readAsDataURL(ev.dataTransfer.items[0]);               
            }
        } else {
            // Use DataTransfer interface to access the file(s)
             if (ev.dataTransfer.files.length > 1) {
                alert("Only single files can be dragged and dropped into Caption Pro Web");
                return;
            }           
            document.getElementById("MainContent_DroppedFileName").value = ev.dataTransfer.files[0].name
            document.getElementById("MainContent_DroppedFileContent").value = "Test";

            reader = new FileReader();
            reader.onload = function (event) {
                 document.getElementById("MainContent_DroppedFileContent").value = event.target.result;
            };
            reader.readAsDataURL(ev.dataTransfer.files[0]);           
        }

        document.getElementById('<%=btnDrop.ClientID %>').click();

    }
</script>

...

    <div id="drop_zone" ondrop="dropHandler(event);" ondragover="dragOverHandler(event);">
    <p>Drag image to this Drop Zone ...</p>
    </div> 
    <asp:HiddenField ID="DroppedFileName" runat="server" />
    <asp:HiddenField ID="DroppedFileContent" runat="server" />
...
 </asp:Content>

我从 c# 访问隐藏字段,如下所示

protected void btnDrop_Click(object sender, EventArgs e)
         {
             string FileName = DroppedFileName.Value;
             string FileContent = DroppedFileContent.Value;
         }

如果我使用 Internet Explorer 作为目标浏览器(不以管理员身份运行 VS,因为这会禁用拖放!)并在 reader.onload() 函数中设置断点,隐藏字段 DroppedFileContent 包含编码的文件内容,但是当我尝试从 btnDrop_Click 访问它只包含 reader.onload() 之前设置的“测试”,不包含编码文件内容。DroppedFileNam.Value 字段与 Javascript 中的设置相同。

于 2019-09-25T03:33:50.127 回答