Flask-strange routing issue - python

So I am trying to test out serving some user uploaded files in Flask. For images I am simply renaming them with a shortened UUID and putting them in a folder, but for other file types I would like to retain the original filename, so I devised the convoluted method of saving each file in a subfolder named with a UUID. Everything works fine, both the images and files upload and are in the directories they should be in. Just to test I made a template for a download page to just display the filename(planned to implement a download button later). However, when I plug the generated URL in for an uploaded file, I get a 404, and the function that url is supposed to be bound to doesn't even appear to execute(I had it print the filename in console and it doesnt even print), and in console the url is displayed: "GET /xVgePgj2Y HTTP/1.1" 404 -
My code for uploading the files and making the URL:
else:
new_folder_name = shortuuid.uuid()[:9]
os.mkdir(os.path.join(app.config['FILE_FOLDER'], new_folder_name))
file.save(os.path.join(os.path.join(app.config['FILE_FOLDER'], new_folder_name), filename))
new_folder_path = os.path.join(app.config['FILE_FOLDER'], new_folder_name)
return url_for('uploaded_file', new_folder_name=new_folder_name)
My code for serving the files:
#app.route('/<new_folder_name>', methods=['GET'])
def uploaded_file(new_folder_name):
filename = subfolder_fetch(new_folder_name)
return render_template("download.html", filename=filename)
and finally my code for fetching the filename from the subdirectory (called in the serving function - didn't pass the filename to the url_for function because that would make it ugly and complicated):
def subfolder_fetch(new_folder_name):
stuff = os.listdir(os.path.join(app.config['FILE_FOLDER'], new_folder_name))
for name in folder:
print (name)
return name
I'm puzzled as to what is even going on and why my uploaded_file function isn't even being called.
Thanks in advance.

Related

My function containing send_file() does not seem to update

I am using a Flask application to update some PDF files, convert them to an Excel file and send this file back to the user. I am using an instance folder to store the pdf and the excel files.
But when the user press the button "Download" in order to download the generated Excel file, an old file is downloaded (from an older session).
Moreover, when I try to change my code, for example, I changed the name of this Excel file: I can see the new name in the instance folder, but when I download the file with the webapp, it is still the old name (and old file). I have no idea where the webapp is looking for this old file...
MEDIA_FOLDER = '/media/htmlfi/'
app = Flask(__name__)
app.config.from_object(Config)
INSTANCE_FOLDER = app.instance_path
app.config['UPLOAD_FOLDER'] = INSTANCE_FOLDER+MEDIA_FOLDER
#app.route('/file/')
def send():
folder = app.config['UPLOAD_FOLDER']
try:
return send_file(folder+ "file.xlsx", as_attachment=True)
finally:
os.remove(folder+ "file.xlsx")
<a href="{{ url_for('send') }}" ><button class='btn btn-default'>DOWNLOAD</button></a>
I am really new to webapp in general, thank you for your help :)
send_file takes a cache_timeout parameter which is the number of seconds you want to cache the download. By default is 12 hours.
return send_file(
file.file_path(),
as_attachment=True,
cache_timeout=app.config['FILE_DOWNLOAD_CACHE_TIMEOUT'],
attachment_filename=file.file_name
)
http://flask.pocoo.org/docs/1.0/api/

Static files are still being served from file system instead of AWS-S3 in Flask

I have a script that generates an image.
That image is saved in a directory inside my OS static folder. image.png is saved in:
-static
-images
-monkeys
- image.png
The server endpoint function should upload the image into my S3-bucket and return that static file from my bucket, not from my OS file system.
This does not work for some reason.
The image uploading works fine, I can see the image in the bucket, I'm just not able to serve the static image, I get an error:
"The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.". Basically it cannot find the image.
I am using flask-S3 in the following way:
app = Flask(__name__)
app.config['FLASKS3_BUCKET_NAME'] = os.environ.get('S3_BUCKET_NAMEING')
app.config['USE_S3_DEBUG'] = True
s3 = FlaskS3(app)
My endpoint for serving the static image:
#app.route('/image/monkey/<address>', methods = ['GET'])
def monkey_image(address):
# There is some code here that generates that image and places it
# inside the monkeys folder. I did not include it because
# it is not relevant to the question
image = open(image_path, 'rb')
S3_path = 'images/monkeysS3/' + monkey_image_name
upload_image_to_s3_bucket(image,'static/' + S3_path)
return redirect(flask_url_for('static', filename=S3_path))
So the last 2 lines matters.
upload_image_to_s3 works. The issue comes from
return redirect(flask_url_for('static', filename=path)).
It just can't find the image inside my S3 bucket.
This goes for development and production as well.
Thanks

Retrieving default fallback avatar image using python and GAE

my users can upload an image of themselves and use that as an avatar. Now I am struggling how to retrieve a default fallback image if they haven't uploaded an image themselves.
The path to the avatar is "//mysite.com/avatar/username".
So far I have this code, which works fine when the user has uploaded an avatar themselves, but it gives me the following error when I try to retrieve the default image:
raise IOError(errno.EACCES, 'file not accessible', filename)
IOError: [Errno 13] file not accessible: '/Users/myuser/Documents/github/mysite/static/images/profile.png'
def get(self):
path = self.request.path.split('/')
action = self.get_action(path)
if action:
e = employees.filter('username = ', action).get()
if e.avatar:
self.response.headers['Content-Type'] = "image/png"
self.response.out.write(e.avatar)
else:
self.response.headers['Content-Type'] = 'image/png'
path = os.path.join(os.path.split(__file__)[0], 'static/images/profile.png')
with open(path, 'r') as f:
print self.response.out.write(f.read())
I have defined the "/static"-folder as a static_dir in my app.yaml.
I know I can place the profile.png in the root-folder, but I prefer to have it in the "/static/images"-folder.
Any ideas?
If you declared the file itself as a static_file or its directory or any directory in its filepath a static_dir inside your app/service's .yaml config file then, by default, it's not accessible to the application code.
You need to also configure it as application_readable. From Handlers element:
application_readable
Optional. Boolean. By default, files declared in static file handlers
are uploaded as static data and are only served to end users. They
cannot be read by an application. If this field is set to true, the
files are also uploaded as code data so your application can read
them. Both uploads are charged against your code and static data
storage resource quotas.

Flask redirect to randomly named folder

I'm building a small app that will (eventually):
Upload a file + process it with a background analysis tool + spit it back out to the user that uploaded it. I'm trying to put each file into a randomly generated folder name to keep things categorized a bit.
To start with, I'm getting the upload redirects working, and they're almost there but I can't seem to get flask to redirect to a randomly generated folder name, even though it exists and the file the user has uploaded is in it.
Here's how I'm accomplishing this...
#app.route('/upload', methods=['POST'])
def upload():
file = request.files['file']
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
foldername = tempfile.mkdtemp(prefix='file', dir='uploads')
file.save(os.path.join(foldername, filename))
return redirect(url_for('uploaded_file', foldername=foldername, filename=filename))
else:
return '<h3>Invalid File, PDF or image only.</h3>'
#app.route('/<foldername>/<filename>')
def uploaded_file(foldername, filename):
return send_from_directory(filename)
On the redirect, the file is in the right place, and the folder is in the right place, and the browser is headed to the right place, but flask 404s it...
192.168.1.69 - - [29/Jan/2017 22:32:19] "GET / HTTP/1.1" 200 -
192.168.1.69 - - [29/Jan/2017 22:32:25] "POST /upload HTTP/1.1" 302 -
192.168.1.69 - - [29/Jan/2017 22:32:25] "GET /uploads/file0wr5ug4y/Screen_Shot_2017-01-25_at_11.23.48_AM.png HTTP/1.1" 404 -
Disregard the last comment to the first string of replies, trial and error figured it out.
The foldername must be passed to the send_from_directory function as well, and more importantly must be prefixed with 'path:' to allow the filename variable value to be a path.
So the final route looks like...
#app.route('/<foldername>/<path:filename>')
def uploaded_file(foldername, filename):
return send_from_directory(foldername, filename)

upload image using image Path in flask

I want to upload an image file to imgur using the python-Flask. So for this I am submitting an image file from the form and want to upload this file to imgur.
But the point is the example snippets given in the imgur api want the path name of the file that was uploaded. So far I was trying to upload but I am stuck!!
This is my main.py file
if request.method == "POST":
image = request.files.get('myfile') #myfile is name of input tag
config ={
'album':album,
'name':'Catastrophe!',
'title':'Catastrophe!'
}
print os.path.realpath(image.filename) # this line gives me wrong path of file.
print "uploading image..."
#image = client.upload_from_path(filepath,config=config,anon=False)
The commented print statement gives me path like this
/home/suraj/Desktop/FlaskTrials/wallpaper.jpg
But the thing is the correct file path could be anything the user wants to choose image from
How do I get this path. Am I doing the right thing to upload the image to imgur api ?
I would be able to do by making an dir in root folder and adding image to it and then get the filename of that and upload to imgur.
But I was wandering is it possible without saving and image file.
Thanks in advance
It looks to me like you forgot to save the file on the server. Here is a modified version of your code based on http://flask.pocoo.org/docs/0.10/patterns/fileuploads/.
if request.method == "POST":
image = request.files['myfile'] #myfile is name of input tag
config ={
'album':album,
'name':'Catastrophe!',
'title':'Catastrophe!'
}
print "uploading image..."
filename = secure_filename(image.filename)
file.save(os.path.join('/home/suraj/Pictures', filename))
print os.path.realpath(image.filename)
I recommend considering restricting the file names to certain extensions, as suggested by the Flask doc.

Categories