Monday, March 20, 2017

Drag and Drop Files with HTML5 and Flask

Doing drag and drop file uploads has interesting uses. Uploading resumes, pictures, and so on are all scenarios where this is handy. So here's a look  at things I think about when it comes to drag and drop file uploads.


The Layout Of The Drop Zone

Since files need to go somewhere, we start by setting up a drop area for them to land in. This just requires a little HTML and CSS. The aim here is a simple box with a border. Code like this should do the trick.




The result looks like this.




And that's all on the look of it. As for DOING something with it, that's another story.

Getting Javascript/JQuery to Handle Drag and Drop

When dragging and dropping into that red square, the browser needs to know how to react. By default, it has its own ideas. That div element will tell you to buzz off if we try dragging stuff over it with the mouse. So we'll throw in a preventDefault invocation to say to the browser "Relax, I got this."

Then there are the drops which are their own kettle of fish. Often times, browsers seem to like popping open a new tab to display dropped content. We don't want that so another preventDefault heads that problem off at the pass.

Now, as for the file, we have to dig into the event to this thing called a dataTransfer. To me, dataTransfer plays the role of a handbag to store things in when taking dragged stuff from point A to point B. I don't know if that's the official definition but, for our purposes, it works.


For the moment, we just fish out the file that got stored there when we dragged it in. Then, we just display the name in the Chrome console. Hey look, a file!

And now I'm bored of Javascript. Let's switch to server side and talk Python. We'll deal with the rest of the client-side of things later.

Using Python And Flask To Give Files Somewhere To Go

Time to escape the browser and hang out in Pycharm and iPython for awhile. The mad plan is to knock out server code that takes in just any old file that wants to come live there.




The code does what it says. We grab the file out of the requests "files" dictionary. Then we put the file name through the Flask "secure_filename" to help prevent users messing with the system via sneaky file names. Save it to the folder and we're done.

Back to Javascript yet? Nah. We can get by fine using requests and ipython to test this code. Banging out something like this should do the trick.

In [11]: from requests import post
In [12]: url = "http://localhost:5000/sendfile"
In [13]: res = post(url, files={"file2upload":open("junkloop.sh", "rt")}
   ....: )
In [14]: res
Out[14]:
In [15]: res.text
Out[15]: 'successful_upload'

Okay, that was easy enough. Check the uploads folder .... it's there. Good. What's next?

Back To Javascript To Upload This Stuff

We can't avoid the client forever so let's get back on that. The thing to do next is to put together a request in a way that does a real upload. To do that, we have to take into account funny quirks as to how browsers like treating file uploads.

One thing to take into account here. Browsers seem to like to turning files into strings that conform to some content type or another. We don't want to mess with content types here. The file should be uploaded just as it is. So what do we do?

Fortunately, jQuery give you a couple of options such as processData and contentType to get around that issue. After making proper modifications, file dropping logic that looks like this.


Now, just double check that uploads folder and say "Hooray, drag and drop uploading works!"


Bonus Round - Listing Uploaded Files

We might as well list the files that are being uploaded. Triggering a fresh list of current files is easy enough. Just attach a request for a fresh list of files as a success response to the upload request. Might as well make the most of those promises, right?  Adding something to the end of dropHandler would be a good start.

        var promise = $.ajax(req);
        promise.then(fileUploadSuccess);

Beyond which you need to implement that function so it actually takes care of getting that fresh list. Easy enough to implement. Standard handlebars templating. Click here and here if curious.


Okay, so then what? That /filenames endpoint in the Flask code. We really should take care of that. But first, a quick tweak to send_file. A line like this after saving the file would be nice.

    # open and close to update the access time.
    with open(save_path, "r") as f:
        pass

The point of this is that I want to see the files in the order that they are uploaded. Doing a quick open/close changes the access time. Now we have files with a chronological upload history.  Coolness!

Oh yes, that /filenames thing. Here's that.


Well, that was kind of weird and hacky. Notice this lambda?

modify_time_sort = lambda f: os.stat("uploads/{}".format(f)).st_atime

So here's an example of sorting based on the access time that you get from the Linux stat command. The "st_atime" stands for "stat access time". That refers to the time the file was last accessed.

One other thing. We know that all those access times are in order of upload time because opening and closing files in /sendfile ensures that.


Let's Dump The Ugly Lambda

But my God this code is awful! That code would have been a lot clearer if I avoided the lambda. Something like this is nicer now that I think of it.


Yeah, that looks better. Avoid cancer in your Python code. Say no to lambda boys and girls.


And Now We Have An End Result

With all being said and done, you now have a setup for uploading files that lists the files you uploaded. It should look a little like this.




FINAL CAVEAT
: If you want to go public with something like this, read stuff on how to manage uploaded files in a secure way. Or let this be a starting point for a silly project that you have no intention of putting into prod. Oh, and here is a link to the Github project this article is based on.  Have fun!

25 comments:

  1. Nice Post! It is really interesting to read from the beginning & I would like to share your blog to my circles, keep sharing…
    Full Stack Training in Hyderabad

    ReplyDelete
  2. I usually read them, take what I think is useful, what tool may suit me, and try to be creative about it in order to fit my needs.

    Many times things are oriented towards others things that I'm interested in.

    But may I say, I found the approach of this article uniquely outstanding. Speaks to me plain, simple, expressing ideas without the need of "marketing induced words" which do not mean nothing unless you unwrap them.https://nareshit.in/html-javascript-training/

    ReplyDelete
  3. thank your valuable content.we are very thankful to you.one of the recommanded blog.which is very useful to new learners and professionals.content is very useful for hadoop learners


    Best Spring Classroom Training Institute
    Best Devops Classroom Training Institute
    Best Corejava Classroom Training Institute
    Best Advanced Classroom Training Institute
    Best Hadoop Training Institute
    Best PHP Training Institute

    ReplyDelete
  4. very nice blogs!!! i have to learning for lot of information for this sites...Sharing for wonderful information. Thanks for sharing this valuable information to our vision. You have posted a trust worthy blog keep sharing

    Digital Marketing In Telugu
    Digital Marketing In Hyderabad
    internet marketing
    Digital marketing
    Digital Marketing Strategy

    ReplyDelete
  5. Thank you for sharing this useful article with us. This blog is a very helpful to me in future. Keep sharing informative articles with us.

    https://www.ahmedabadcomputereducation.com/course/php-training-course/

    ReplyDelete
  6. Very interesting blog. Many blogs I see these days do not really provide anything that attracts others, but believe me the way you interact is literally awesome.

    Devops Training in Gurgaon
    Docker Kubernetes training in Gurgaon

    ReplyDelete
  7. Thank you for sharing this useful article. This blog is a very helpful to me. Keep sharing informative articles with us.

    https://www.france-collectivites.fr/

    ReplyDelete
  8. Great sources for knowledge. Thank you for sharing this helpful article. It is very useful for me.

    https://www.ahmedabadcomputereducation.com/course/laravel-training-course/

    ReplyDelete
  9. Thank you for sharing this useful article with us. This blog is a very helpful to me. Keep sharing informative articles with us.

    https://www.sdsfin.in/services/project-finance-consultants-in-ahmedabad/

    ReplyDelete
  10. Thank You for sharing this informative article.

    https://web30india.com/

    ReplyDelete
  11. it’s really nice and meanful. it’s really cool blog. Linking is very useful thing.you have really helped lots of people who visit blog and provide them usefull information.
    Data Science Training in Hyderabad

    I am really happy to say it’s an interesting post to read . I learn new information from your article , you are doing a great job . Keep it up

    Devops Training in Hyderabad

    Hadoop Training in Hyderabad

    Python Training in Hyderabad

    Tableau Training in Hyderabad

    Selenium Training in Hyderabad

    informatica Training in Hyderabad

    datastage Training in Hyderabad

    ReplyDelete
  12. Thank you for sharing this Blog, This is more informative and nice.

    Java Real-World Project (click Here)

    ReplyDelete
  13. This comment has been removed by the author.

    ReplyDelete
  14. Upgrade your career clinical data mange ment from industry experts gets complete hands on servicess, on our sclinbio.

    ReplyDelete
  15. vYahoo! offers an additional layer of security through the two-step verification process. Some users like the feature while others find in troublesome to enter two verification passwords on every sign in. Here is a guide for both types of users to enable and disable two-step verification in their Yahoo! Mail account. sclinbio.com

    ReplyDelete
  16. This is a good web site and alos very useful content i like this web site thanks for sharing this blog our https//.Sclinbio./com

    ReplyDelete
  17. Nice blog...We value the devotion you have shown to this site. Anticipate further excellent material.
    Keep posting more

    ReplyDelete
  18. Nice article, especially the way you explained it.
    Keep writing...

    TOSCA Training in Hyderabad

    ReplyDelete