From: Nick Retallack Date: Sun, 4 Oct 2009 08:55:36 +0000 (-0700) Subject: rudimentary file uploading. Saves as sha1 like git objects. code is in lib. needs... X-Git-Url: http://git.veekun.com/zzz-floof.git/commitdiff_plain/5837da26db915faca89925c39fa83202bfb84e32?ds=inline;hp=--cc rudimentary file uploading. Saves as sha1 like git objects. code is in lib. needs db support. --- 5837da26db915faca89925c39fa83202bfb84e32 diff --git a/.gitignore b/.gitignore index 77508f0..bc97b44 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ *.egg/ *.egg-info/ data/ +public/art/* diff --git a/development.ini b/development.ini index bd6fc70..0c39bba 100644 --- a/development.ini +++ b/development.ini @@ -19,6 +19,7 @@ port = 5000 use = egg:floof full_stack = true static_files = true +art_root = %(here)s/public/art cache_dir = %(here)s/data beaker.session.key = floof @@ -36,7 +37,7 @@ sqlalchemy.url = sqlite:///%(here)s/development.db # WARNING: *THE LINE BELOW MUST BE UNCOMMENTED ON A PRODUCTION ENVIRONMENT* # Debug mode will enable the interactive debugging tool, allowing ANYONE to # execute malicious code after an exception is raised. -set debug = false +# set debug = false # Logging configuration diff --git a/floof/controllers/art.py b/floof/controllers/art.py new file mode 100644 index 0000000..dd06f12 --- /dev/null +++ b/floof/controllers/art.py @@ -0,0 +1,29 @@ +import logging + +from pylons import request, response, session, tmpl_context as c, config +from pylons.controllers.util import abort, redirect_to + +from floof.lib.base import BaseController, render + +log = logging.getLogger(__name__) + + + +from floof.lib.file_storage import save_file + +class ArtController(BaseController): + + # def index(): + # c.artwork = Art.query.order_by(Art.id.desc()).all() + # return render + + def new(self): + """ New Art! """ + return render("/art/new.mako") + + + def upload(self): + file = request.POST['file'] + root = config['app_conf']['art_root'] + save_file(root, file) + redirect_to(controller="main", action="index") diff --git a/floof/lib/file_storage.py b/floof/lib/file_storage.py new file mode 100644 index 0000000..5595e88 --- /dev/null +++ b/floof/lib/file_storage.py @@ -0,0 +1,58 @@ +# This sucks. Make it not suck. +import os, shutil, tempfile, hashlib + +chunk_size = 1024*1024 # TODO: is this a good chunk size? + +""" +Notes: +# Here's one way to move stuff... +shutil.copyfileobj(temp.file, dest_file) + +# we should probably store the basename of the original filename in the database somewhere +temp_base = os.path.basename(temp.filename) + +# You can get a mime type like so: +from mimetypes import guess_type +guess_type(temp.filename)[0] +""" + + +def save_file(dest_root, temp): + # we don't know where we're going to save this stuff yet, + # so I guess we'll write it to another tempfile. One we know the path of. + # I'm assuming the tempfile we get from pylons is set to delete itself + # when it closes, and has no visible path. Maybe I'm wrong? + intermediate_file_descriptor, intermediate_path = tempfile.mkstemp() + + # that function gives me an integer file descriptor for some reason. + intermediate_file = os.fdopen(intermediate_file_descriptor, "wb") + + sha1 = hashlib.sha1() + while 1: + data = temp.file.read(chunk_size) + if not data: + break + sha1.update(data) + intermediate_file.write(data) + + temp.file.close() + intermediate_file.close() + hash = sha1.hexdigest() + + # git convention: first two characters are the directory + dest_dir = os.path.join( dest_root, hash[:2] ) + dest_path = os.path.join( dest_dir, hash[2:] ) + + makedirs(dest_dir) + os.rename(intermediate_path, dest_path) + + return hash + + + +def makedirs(dir): + try: + os.makedirs(dir) + except OSError: + pass + \ No newline at end of file diff --git a/floof/lib/helpers.py b/floof/lib/helpers.py index 878b888..ff55eb6 100644 --- a/floof/lib/helpers.py +++ b/floof/lib/helpers.py @@ -5,3 +5,11 @@ available to Controllers. This module is available to templates as 'h'. """ # Import helpers as desired, or define your own, ie: #from webhelpers.html.tags import checkbox, password +from webhelpers import * +from routes import url_for, redirect_to + +from webhelpers.html.tags import * +from webhelpers.html import literal +from webhelpers.pylonslib import Flash +import sqlalchemy.types as types +flash = Flash() diff --git a/floof/model/art.py b/floof/model/art.py index 517fea0..725b9e8 100644 --- a/floof/model/art.py +++ b/floof/model/art.py @@ -8,4 +8,5 @@ from elixir import Entity, Field, Integer, Unicode class Art(Entity): title = Field(Unicode(120)) + # filename = Field(Unicode(120)) diff --git a/floof/templates/art/new.mako b/floof/templates/art/new.mako new file mode 100644 index 0000000..4988917 --- /dev/null +++ b/floof/templates/art/new.mako @@ -0,0 +1,9 @@ +<%inherit file="/base.mako" /> + +

Add New Art

+

Now: Upload a file. Later: Supply a link? Not exclusive to uploading.

+ +${h.form(h.url_for(controller='art', action='upload'), multipart=True)} +${h.file('file')} +${h.submit('submit', 'Upload!')} +${h.end_form()} \ No newline at end of file diff --git a/floof/templates/upload_art.mako b/floof/templates/upload_art.mako new file mode 100644 index 0000000..e69de29 diff --git a/floof/tests/functional/test_art.py b/floof/tests/functional/test_art.py new file mode 100644 index 0000000..e82d5c8 --- /dev/null +++ b/floof/tests/functional/test_art.py @@ -0,0 +1,7 @@ +from floof.tests import * + +class TestArtController(TestController): + + def test_index(self): + response = self.app.get(url(controller='art', action='index')) + # Test response... diff --git a/floof/todo.txt b/floof/todo.txt new file mode 100644 index 0000000..f9a7cd0 --- /dev/null +++ b/floof/todo.txt @@ -0,0 +1 @@ +-- uploading files \ No newline at end of file