Quick images uploader for your blog. A real time saver!
Laziness is the ultimate locomotive of the Progress. Many times I realize that I need a much simpler and more efficient image uploading mechanism, simpler than the regular and annoying file dialog, and even easier than an FTP client. That's why I wrote the script below. You can just copy-paste it into your new python file, name it like upload_image.py. The script asked me to allow him to explain to you about what he's doing, and I gladly agreed with him, so what's following next - is his own explanation of the process.
Let's say my owner has a small food blog, such as this one. For each post, there can be from one to an infinite number of images. To reduce the image size, my owner needs to reduce the jpegs' sizes using, for example, the neatest David's Batch Processor. The owner is a lazy user who always leaves the minimized images in the same directory with the originals (don't ask, they sometimes think that 'directory' is a bad word). Now the jpegs' sizes are all around 45k-50k, but I want to reduce them even more (bandwidth is my other friend). I run
exiv2 rm *.jpg
, which removes all the thumbnails and other unneeded data from images, and now they're just as small as I wanted them to be. Then, I move the original files into another directory on the same level as the original directory, make a gzip archive and upload it: I connect to the server, go to the images directory and unzip the archive, with the containing directory. I also output some tags, so my owner would just copy-paste them into his html editor, or whatever this person has there.
As you can see, I have some settings, and to use me you should change things like username, port etc., there aren't much. And you can run me from command line by typing
python upload_pics.py -d path/to/the/images/directory
I'll ask you for your remote server password if you don't mind. Oh, and you'll need to install all the required libs which I have in the #import declaration - but only if you don't have them already.. Just select them from Synaptic or something. And please have exiv2 installed as well. That's quite it. And, hee-hee, you know, you can't ask me question, because I'm just a script so, use me, and drink more beer on your free time.
#!/usr/bin/env python # By Val Kotlarov @webdesignpatterns.org # This will upload files and extract them. import base64, getpass, os, socket, sys, traceback, tarfile, getopt, paramiko, shutil import pyexiv2 # settings go here username = 'username' # change with your username port = 22 # your connection's port number, 22 is the default hostname = 'example.com' # change with domain or static ip address remote_images_directory = '/path/to/your/images/directory/' # set to where the images directory is max_file_size = 150000 # maximum size in bytes for images to be papcked and uploaded remote_upload_file_path = remote_images_directory+'upload.tar.gz' password = getpass.getpass('Password for %s@%s: ' % (username, hostname)) # end settings # get files in directory which are greater than given size in bytes def listDirectory(directory, minFileByteSize): "get list of file info objects for files of particular extensions" fileList = [os.path.join(directory, os.path.normcase(f)) for f in os.listdir(directory)] #filter by file size fileList = [f for f in fileList if os.path.getsize(f) > minFileByteSize] return fileList try: opts, args = getopt.getopt(sys.argv[1:], "d:v", ["help", "output="]) except getopt.GetoptError, err: # print help information and exit: print str(err) # will print something like "option -a not recognized" sys.exit(2) input_dir = None # the directory to be uploaded for o, a in opts: if o in ("-d", "--directory"): input_dir = a else: assert False, "unhandled option" exit(0) # setup logging paramiko.util.log_to_file('upload_pics.log') # move big files to a new directory on the same level big_files = listDirectory(input_dir, max_file_size) # ~150k if big_files != []: os.mkdir(input_dir + '_big') for f in big_files: shutil.move(f, input_dir + '_big/'+os.path.basename(f)) #print html for images files = listDirectory(input_dir, 0) for f in files: print '' # remove exiv info os.system("exiv2 rm " + input_dir + "/*.jpg") # store into tar file, having the archive's directory name tar = tarfile.open(input_dir + "/upload.tar.gz", "w:gz") # add this directory and its contents, without path to it! tar.add(input_dir, arcname=os.path.basename(input_dir), recursive=True) tar.close() # get host key, if we know one hostkeytype = None hostkey = None try: host_keys = paramiko.util.load_host_keys(os.path.expanduser('~/.ssh/known_hosts')) except IOError: try: # try ~/ssh/ too, because windows can't have a folder named ~/.ssh/ host_keys = paramiko.util.load_host_keys(os.path.expanduser('~/ssh/known_hosts')) except IOError: print '*** Unable to open host keys file' host_keys = {} if host_keys.has_key(hostname): hostkeytype = host_keys[hostname].keys()[0] hostkey = host_keys[hostname][hostkeytype] print 'Using host key of type %s' % hostkeytype # now, connect and use paramiko Transport to negotiate SSH2 across the connection try: t = paramiko.Transport((hostname, port)) t.connect(username=username, password=password, hostkey=hostkey) sftp = paramiko.SFTPClient.from_transport(t) # upload print 'Inside directory: ' + input_dir sftp.put(input_dir+'/upload.tar.gz', remote_upload_file_path) print 'Uploaded file' ch = t.open_channel(kind = "session") ch.exec_command('cd '+ remote_images_directory+' && tar xzf upload.tar.gz') print 'Finished.' sftp.close() t.close() except Exception, e: print '*** Caught exception: %s: %s' % (e.__class__, e) traceback.print_exc() try: sftp.close() t.close() except: pass sys.exit(1)