I have a Flask application on DigitalOcean that creates a file(shapefile), and later on reads it again. How to write the paths of that file, to make sure it can be read later again?
Use paths relative to your application's root.
In Flask the application object ( app ) has a .root_path attribute you can use to create absolute paths to your files. Like:
with open(os.path.join(app.root_path, 'shapefiles', file_name), 'w') as f:
f.write(....)
and later the reverse
with open(os.path.join(app.root_path, 'shapefiles', file_name), 'r') as f:
data = f.read(....)
Related
I am stuck with a really weird problem.
I have a file called: "test.txt".
It is in the same directory with views.py. But I can't read it... FileNotFoundError.
But if I create read_file.py in the same directory with views.py and test.txt, it works absolutely fine.
What is wrong with views? Is this some sort of restriction by Django?
This code works on read_file, doesn't work on views.py:
fkey = open("test.txt", "rb")
key = fkey.read()
I think the problem may be relative vs absolute file handling. Using the following Python snippet, you can work out where the interpreter's current working directory is:
import os
print(os.getcwd())
You should notice it's not in the same directory as the views.py, as views.py is likely being invoked/called from another module. You may choose to change all your open calls to include the whole path to these files, or use an implementation like this:
import os
# This function can be used as a replacement for `open`
# which will allow you to access files from the file.
def open_relative(path, flag="r"):
# This builds the relative path by joining the current directory
# plus the current filename being executed.
relative_path = os.path.join(os.path.dirname(__file__), path)
return open(relative_path, flag) # return file handler
Then, this should work:
fkey = open_relative("test.txt", "rb")
key = fkey.read()
Hope this helps!
This question already has an answer here:
Refering to a directory in a Flask app doesn't work unless the path is absolute
(1 answer)
Closed 5 years ago.
I want to store any uploaded image to the static/customlogos folder with the name "logo.png" no matter what its actual name is. I have a basic Flask setup with the typical static and template folders. For simplicity I removed things like extension validation in my code below. However doing it like this throws a FileNotFound error. Since I want to run my app on various environments, I don't want to use a static path. What am I doing wrong? Thanks for your help.
latestfile = request.files['customlogo']
#This prints the file name of the uploaded file
print(latestfile.filename)
#I want to save the uploaded file as logo.png. No matter what the uploaded file name was.
latestfile.save(os.path.join('/static/customlogos', 'logo.png'))
Obviously, you want to save uploaded file as static/customlogos/logo.png, path that is relative to your Flask application directory, but you have specified the absolute non-existing path /static/customlogos.
Furthermore, according to your comments you are developing under Windows, which adds inconsistency to your question.
In any case, to achieve what you want, you need to know the absolute path of your application, and use it as a starting point:
latestfile.save(os.path.join(app.root_path, 'static/customlogos/logo.png'))
Cross-platform variant:
latestfile.save(os.path.join(app.root_path, 'static', 'customlogos', 'logo.png'))
Ninja dust-proof variant:
latestfile.save(os.path.join(app.root_path, app.config['STATIC_FOLDER'], 'customlogos', 'logo.png'))
You can simplify the operation like below:
from flask import Flask, request, session, g, redirect
from flask import url_for, abort, render_template, flash, jsonify
import os
# Create two constant. They direct to the app root folder and logo upload folder
APP_ROOT = os.path.dirname(os.path.abspath(__file__))
UPLOAD_FOLDER = os.path.join(APP_ROOT, 'static', 'customlogos')
# Configure Flask app and the logo upload folder
app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
# In controller save the file with desired name
latestfile = request.files['customlogo']
full_filename = os.path.join(app.config['UPLOAD_FOLDER'], 'logo.png')
latestfile.save(full_filename)
N.B.: Ensure that you have created customlogos in static folder.
I need to upload an image file to a certain folder. It works fine on localhost but if I push the app to heroku it tells me:
IOError: [Errno 2] No such file or directory: 'static/userimg/1-bild-1.jpg'
Which means it cant find the folder?
I need to store the image files there for a few seconds to perform some actions on theme. After that they will be sent to AWS and will be deleted from the folder.
Thats the code where I save the images into the folder:
i = 1
for key, file in request.files.iteritems():
if file:
filename = secure_filename(str(current_user.id) + "-bild-"+ str(i) +".jpg")
file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
i = i + 1
Later I get the files from the folder like this:
for item in os.listdir(os.path.join(app.config['UPLOAD_FOLDER'])):
if item.startswith(str(current_user.id)) and item.split(".")[0].endswith("1"):
with open(os.path.join(app.config['UPLOAD_FOLDER'], item), "rb") as thefile:
data = base64.b64encode(thefile.read())
upload_image_to_aws_from_image_v3('MYBUCKET', "userimg/", data, new_zimmer, "hauptbild", new_zimmer.stadt, new_zimmer.id)
os.remove(str(thefile.name))
That is the upload folder in app config:
UPLOAD_FOLDER = "static/userimg/"
Everything works fine on localhost.
I had to add the absolute path to the directory, because the path on the server is different.
You can run heroku run bash for your app through the CLI and check the directories with dir. Use then cd .. to go back or cd *directory name* to go into the directory.
I had to add
MYDIR = os.path.dirname(__file__)
and replace all
os.path.join(app.config['UPLOAD_FOLDER']
with
os.path.join(MYDIR + "/" + app.config['UPLOAD_FOLDER']
Some informations on the topic also here:
Similar question
I am getting a file posting from a file:
file = request.post['ufile']
I want to get the path. How can I get it?
You have to use the request.FILES dictionary.
Check out the official documentation about the UploadedFile object, you can use the UploadedFile.temporary_file_path attribute, but beware that only files uploaded to disk expose it (that is, normally, when using the TemporaryFileUploadHandler uploads handler).
upload = request.FILES['ufile']
path = upload.temporary_file_path
In the normal case, though, you would like to use the file handler directly:
upload = request.FILES['ufile']
content = upload.read() # For small files
# ... or ...
for chunk in upload.chunks():
do_somthing_with_chunk(chunk) # For bigger files
You should use request.FILES['ufile'].file.name
you will get like this /var/folders/v7/1dtcydw51_s1ydkmypx1fggh0000gn/T/tmpKGp4mX.upload
and use file.name, your upload file have to bigger than 2.5M.
if you want to change this , see File Upload Settings
We cannot get the file path from the post request, only the filename, because flask doesn't has the file system access. If you need to get the file and perform some operations on it then you can try creating a temp directory save the file there, you can also get the path.
import tempfile
import shutil
dirpath = tempfile.mkdtemp()
# perform some operations if needed
shutil.rmtree(dirpath) # remove the temp directory
I tried to read a file in a view like this:
def foo(request):
f = open('foo.txt', 'r')
data = f.read()
return HttpResponse(data)
I tried to place the foo.txt in almost every folder in the project but it still returns
[Errno 2] No such file or directory:
'foo.txt'
So does anybody knows how to open a file in app engine patch? Where should i place the files i wish to open? many thanks.
I'm using app-engine-patch 1.1beta1
In App Engine, patch or otherwise, you should be able to open (read-only) any file that gets uploaded with your app's sources. Is 'foo.txt' in the same directory as the py file? Does it get uploaded (what does your app.yaml say?)?
Put './' in front of your file path:
f = open('./foo.txt')
If you don't, it will still work in App Engine Launcher 1.3.4, which could be confusing, but once you upload it, you'll get an error.
Also it seems that you shouldn't mention the file (or its dir) you want to access in app.yaml. I'm including css, js and html in my app this way.
You should try f = open('./foo.txt', 'r')