最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Passing path to uploaded file from HTML5 drag & drop to input field - Stack Overflow

programmeradmin2浏览0评论

I'm working on an application (in Node.js, which is irrelevant for this case) which allows the user to upload an image. It works fine using a form with an input (type="file") field.

However, what I want is to be able to upload an image using HTML5 drag and drop instead. As far as i've come it's possible to drag an image to the client, and the image thumbnail is displayed in a div. However I really need some help with getting the file upload working.

The thing is that I want to use the form that i'm using right now, and (somehow) pass the file's path to the input field, i.e. the flow will work exactly as it do now, but instead of choosing a file by browsing it I want to attach it to the input field by drag and drop.

In the js code below for drag and drop the file that was dragged to the client is stored in the variable "file", and i'm able to use "file.name", "file.type" and "file.size" exactly the same way as it works since before with the form. However, I can't access the files "path" (file.path) which makes it impossible to access the file server side for uploading the same way as I do it since before.

The question is, is it possible to pass the file object to the input field after the file has been dragged to the client, so that I can click on "submit" and upload the file? If so, how could this be done?

Thanks in advance!

the dropbox as well as the form i'm using for file uploads:

<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>

the code for drag and drop:

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;
    };
},

I'm working on an application (in Node.js, which is irrelevant for this case) which allows the user to upload an image. It works fine using a form with an input (type="file") field.

However, what I want is to be able to upload an image using HTML5 drag and drop instead. As far as i've come it's possible to drag an image to the client, and the image thumbnail is displayed in a div. However I really need some help with getting the file upload working.

The thing is that I want to use the form that i'm using right now, and (somehow) pass the file's path to the input field, i.e. the flow will work exactly as it do now, but instead of choosing a file by browsing it I want to attach it to the input field by drag and drop.

In the js code below for drag and drop the file that was dragged to the client is stored in the variable "file", and i'm able to use "file.name", "file.type" and "file.size" exactly the same way as it works since before with the form. However, I can't access the files "path" (file.path) which makes it impossible to access the file server side for uploading the same way as I do it since before.

The question is, is it possible to pass the file object to the input field after the file has been dragged to the client, so that I can click on "submit" and upload the file? If so, how could this be done?

Thanks in advance!

the dropbox as well as the form i'm using for file uploads:

<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>

the code for drag and drop:

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;
    };
},
Share Improve this question edited Oct 7, 2012 at 23:59 challet 97210 silver badges22 bronze badges asked May 8, 2012 at 14:14 holyredbeardholyredbeard 21.2k32 gold badges111 silver badges174 bronze badges 1
  • It would really help if you could recreate the issue using jsfiddle.net. – tw16 Commented May 13, 2012 at 15:50
Add a comment  | 

3 Answers 3

Reset to default 8

You cannot use the file input to add the file data. Nevertheless, what you can do (among other technics) is to use the base64 (natively available through the reader.onload event as event.target.result, when using readAsDataURL method) encoded data and put it into an hidden field :

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);

From the server side you'll be able to get the base64 encoded data from the file, just decode it and use it as you want.

While submitting the form, you could also change the "enctype" attribute (done through the formenctype attribute) and remove the basic html file input, since the data will be post in a text field.

It is impossible to know the path of the field for security purposes. With drag and drop you must have it upload independently of the main form. Look here for an example: http://www.sitepoint.com/html5-file-drag-and-drop/

I find that the hidden field set in reader.onload (see answer by @challet) is not set when acccessed in code behind. I am using asp.net and a WebForms project. To access the hidden fields I have to prepend MainContent_ to the field names. aspx code is below


<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>

I access the hidden fields from c# as shown below

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

If I use Internet Explorer as the target browser (not running VS as Admin as this disables drag/drop!) and set a breakpoint in the reader.onload() function the hidden field DroppedFileContent contains the encoded file content, but when I try to access it from btnDrop_Click it only contains "Test" as set before reader.onload() and does not contain the encoded file content. The field DroppedFileNam.Value is as set in the Javascript.

发布评论

评论列表(0)

  1. 暂无评论