Victor Elias Rodriguez Victor Elias Rodriguez - 7 months ago 81
Python Question

Uploading and Processing a CSV File using Bottle; Possible Encoding Issue

I am trying to upload and process a CSV file via an HTML form using Bottle. I've already created a working example with Tkinter; the CSV uploads nicely and all data, including the hashed passwords get into the Sqlite3 database.

WORKING TKINTER CODE ...

import os
import sqlite3
import csv
from pbkdf2 import crypt
from tkinter import *
from tkinter import filedialog
root = Tk()
root.geometry("500x500")

def open1():
filename = filedialog.askopenfilename()
with open(filename,"r") as s_info:
reader = csv.reader(s_info)
for x in reader:
pwhash = crypt(x[1])
connection = sqlite3.connect("users.db")
cursor_v = connection.cursor()
cursor_v.execute("insert into users (cemail, cpassword) values (?,?)", (x[0],pwhash))
connection.commit()
cursor_v.close()
else:
print("CSV Uploaded")

x = Button(text="Open",command=open1).pack()


The issue is when I try to re-create the the code in Bottle, I get the following error:

BOTTLE CODE - HTML:

<form action="/panel" method="post" enctype="multipart/form-data">
<input type="file" name="data" />
<input type="submit">
</form>


BOTTLE CODE - ROUTE:

@route('/panel', method='POST')
def do_upload():
data = request.files.data
with open(data,"r") as s_info:
reader = csv.reader(s_info)
for x in reader:
pwhash = crypt(x[1])
connection = sqlite3.connect("users.db")
cursor_v = connection.cursor()
cursor_v.execute("insert into users (cemail, cpassword) values (?,?)", (x[0],pwhash))
connection.commit()
cursor_v.close()
else:
return "<p>CSV Uploaded</p>"


ERROR:

with open(data,"r") as s_info:
TypeError: invalid file: <bottle.FileUpload object at 0x105cb84d0>


Any help is appreciated

Answer

request.files.data is a FileUpload object. It has an attribute named file, so:

EDIT: Updated to handle byte streams given by urllib with python-3.x.

import codecs

def do_upload():
    reader = csv.reader(codecs.iterdecode(request.files.data.file, 'utf-8'))
    for x in reader:
        ...

should work, making your bottle code look like this:

import codecs

@route('/panel', method='POST')
def do_upload():
    reader = csv.reader(codecs.iterdecode(request.files.data.file, 'utf-8'))
    for x in reader:
        pwhash = crypt(x[1])
        connection = sqlite3.connect("users.db")
        cursor_v = connection.cursor()
        cursor_v.execute("insert into users (cemail, cpassword) values (?,?)", (x[0],pwhash))
        connection.commit()
        cursor_v.close()
    else:
        return "<p>CSV Uploaded</p>"