Can't read file from secure_filename(f.filename) - python

I need to get a binary file from wtforms and store it as bytea in postgresql. And I don't need to store it permanently as a file. From my understanding of the Flask offical doc I shall be able to access the filename through either request.files.['myfile'].filename or secure_filename(f.filename). However, both of them give me a error: IOError: [Errno 2] No such file or directory: u'myuploadpdf.pdf'
f = request.files.['myfile']:
if f and allowed_file(f.filename):
#filename = secure_filename(f.filename)
data = open(f.filename, 'rb').read()
#data = open(filename , 'rb').read()
binary = psycopg2.Binary(data)

open() expects a pathname to the file. Since the file hasn't been saved to disk, no such path exists. :)
What you actually want to do is call f.read() directly. Reading incoming files is covered here.
Also, definitely use secure_filename() if you work with anything on disk. Don't want to open yourself to any directory traversal attacks down the line.

The objects in request.files are FileStorage objects and they have the same methods as normal file objects in python. So to get the contents of the file as binary, try doing this:
data = request.files['myfile'].read()

Related

zipfile.BadZipFile: Bad offset for central directory

I have designed a webpage that allows the user to upload a zip file. What I want to do is store this zip file directly into my sqlite database as a large binary object, then be able to read this binary object as a zipfile using the zipfile package. Unfortunately this doesn't work because attempting to pass the file as a binary string in io.BytesIO into zipfile.ZipFile gives the error detailed in the title.
For my MWE, I exclude the database to better demonstrate my issue.
views = Blueprint('views', __name__)
#views.route("/upload", methods=["GET", "SET"])
def upload():
# Assume that file in request is a zip file (checked already)
f = request.files['file']
zip_content = f.read()
# Store in database
# ...
# at some point retrieve the file from database
archive = zipfile.ZipFile(io.BytesIO(zip_content))
return ""
I have searched for days on-end how to fix this issue without success. I have even printed out zip_content and the contents of io.BytesIO(zip_content) after applying .read() and they are exactly the same string.
What am I doing wrong?
Solved. Using f.read() only gets the name of the zip file. I needed to use f.getvalue() instead to get the full file contents.

How do I create and write in a json file object in Python, without having to store it locally?

I want to store data in a JSON file as an object in Python without having to store it locally, but I have not found any way of doing this! Currently, I create a file locally like so:
open(local_file_name + '.json', 'wb').write(file.content)
and then I proceed to use it for various functions. The problem, however, is that I create multiple of these files, so many in fact that it would simply be easier for me if I could somehow make them objects instead. Any suggestions?
It seems my code lacked one very important line of code: file.close()
Here is my code. Perhaps the data is stored locally for some time, but there is no JSON file created within the directory.
local_path = os.getcwd()
local_file_name = 'example.json'
f = open(local_file_name, 'wb')
f.write(file.content)
f.close()
upload_file_path = os.path.join(local_path, local_file_name)
Now I can upload the file object!

Django Python save database blog posts to a zipfile?

I have a django blog and want to download a backup zipfile with all the entries. The blog post text content is stored in the database.
I have written this code with the goal of trying to get the zipfile to save a bunch of .txt files in the main zip directory, but all this code does is outputs a single corrupted zip file. It cannot be unzipped but for some reason it can be opened in Word and it shows all of the blog post text mashed up.
def download_backups(request):
zip_filename = "test.zip"
s = BytesIO()
zf = zipfile.ZipFile(s, "w")
blogposts = Blog.objects.all()
for blogpost in blogposts:
filename = blogpost.title + ".txt"
zf.writestr(filename, blogpost.content)
resp = HttpResponse(s.getvalue())
resp['Content-Disposition'] = 'attachment; filename=%s' % zip_filename
return resp
Any help is appreciated.
Based on this answer to another question, you may be having an issue with the read mode. You'll also need to call zf.close(), either explicitly or implicitly, before the file will actually be complete.
I think there's a simpler way of handling this using a temporary file, which should have the advantage of not needing to fit all of the file's contents in memory.
from tempfile import TemporaryFile
from zipfile import ZipFile
with TemporaryFile() as tf:
with ZipFile(tf, mode="w") as zf:
zf.writestr("file1.txt", "The first file")
zf.writestr("file2.txt", "A second file")
tf.seek(0)
print(tf.read())
The with blocks here will result in your temp file going out of scope and being deleted, and zf.close being called implicitly before you attempt to read the file.
If the goal here is just to back up the data rather than using this specific format, though, I'd suggest using the built-in dumpdata management command. You can call it from code if you want to serve the results through a view like this.

How to create a file in a different directory? (python)

I am currently stuck with the following error:
IOError: [Errno 2] No such file or directory: '/home/pi/V1.9/Storage/Logs/Date_2018-08-02_12:51.txt'
My code to open the file is the following:
nameDir = os.path.join('/home/pi/V1.9/Storage/Logs', "Date_" + now.strftime("%Y-%m-%d_%H:%M") + ".txt")
f = open(nameDir, 'a')
I am trying to save a file to a certain path, which is /home/pi/V1.9/Storage/Logs. I am not sure why it can't find it, since I have already created the folder Logs in that space. The only thing being created is the text file. I am not sure if its suppose to join up like that, but I generally tried to follow the stages on this thread: Telling Python to save a .txt file to a certain directory on Windows and Mac
The problem seems to be here:
f = open(nameDir, 'a')
'a' stands for append, which means: the file should already exist, you get an error message because it doesn't. Use 'w' (write) instead, Python will create the file in that case.
If you are creating the file use the write mode w or use a+
f = open(nameDir, 'w')
f = open(nameDir, 'a+')
Use only a append if the file already exist.
Not really an answer to your question, but similar error. I had:
with open("/Users//jacobivanov/Desktop/NITL/Data Analysis/Completed Regressions/{0} Temperature Regression Parameters.txt".format(data_filename), mode = 'w+') as output:
Because data_filename was in reality a global file path, it concatenated and looked for a non-existent directory. If you are getting this error and are referring to the file path of an external file in the name of the generated file, check to verify it isn't doing this.
Might help someone.

having trouble opening a csv file in web2py

I'm working on a project in web2py where I need to upload a csv file to a database, then take the information that is in that file and do something with it. I am able to upload a csv file, and in the database I can click on this file, open it, and physically read it, but when I try to open and read it in the controller it doesn't work.
The code in my controller that causes the error looks like this:
csvfile = open(form.vars.csv, 'r')
the error is "FileNotFoundError: [Errno 2] No such file or directory: 'datab.csv.aae72db13bc450af.637376746573742e637376.csv'
"
why is this not working?
After the form has been processed, the upload field in the database, and therefore form.vars.csv, simply stores the filename, not the full file path. Rather than manually constructing the full file path and calling open, more simply you can just do:
filename, csvfile = db.mytable.csv.retrieve(form.vars.csv)
When passed a file name, the .retrieve method of an upload field object returns the original (untransformed) file name as well as the open file object.
See http://web2py.com/books/default/chapter/29/06/the-database-abstraction-layer#More-on-uploads.

Categories