How to write path in flask of folder in remote server - python

I'm creating a RESTful service using Flask,that parses files into a .zip folder, and I want to return that file. this is a snippet of the code.
from flask import Flask, send_from_directory
import zipfile
#app.route('/get_files', methods=['GET'])
def download():
zf = zipfile.ZipFile('gen.zip', mode = 'w')
zf.write('generated/file1.c')
zf.write('generated/file2.c')
zf.write('generated/file3.c')
zf.write('generated/file4.h')
zf.close()
return send_from_directory(/home/localadmin/test", "gen.zip", as_attachment=True)
it's working perfectly on localhost. when I run it on a remote server, I get 404 Not Found. So I think the issue is from the path to the directory?
EDIT:
I have tried returning a string instead of the generated files, and it's working perfectly too. what comes to my mind are two issues:
1. the path to the server directory is wrong
2. the server's proxy configurations does not permit file downloads maybe?

Related

Serving media file to podcast.app (iOS/MacOS) for download

I'm trying to create a simple podcast hosting web server with flask.
Streaming media files from the server works beautifully. However whenever I try and download the media for offline viewing my podcast app throws "Download error".
I've tried all sorts of headers and responses.
End point I'm using with relevant code (I hardcoded the filename for testing):
import os
import logging
from streamlink.exceptions import (PluginError)
from flask import Flask, redirect, abort, request
from flask import send_from_directory
def run_server(host, port, file_dir):
#app.route('/media', methods=['GET'])
def media():
return send_from_directory(file_dir, '6TfLVL5GeE4.mp4')
app.run(host=host, port=port, debug=True)
Podcast.app error log states:
Download failed due to error: Invalid asset: The original extension and resolved extension were not playable for episode url Optional(http://10.0.0.115:8084/media?id=6TfLVL5GeE4&provider=tw).
I can't for the life of me figure why it would fail for downloading but stream perfectly fine.
Please help!
Found out that you can not use parameters for a podcast feed url.
The url must include a filename.
For example: http://localhost/file.mp3

400 Bad Request when uploading files [Flask on Cloud9]

I'm having trouble resolving this issue. I've got a very simple file upload form that I'm getting the following error for:
Bad Request
The browser (or proxy) sent a request that this server could not understand.
I've followed a basic tutorial and copied it exactly. I'm wondering if it's because of some permissions thing as I'm using the Cloud9 IDE and just trying to upload the files into a folder I've created in the root of the site.
application.py is as follows:
from cs50 import SQL
import os
from flask import Flask, jsonify, redirect, render_template, request
# Configure application
app = Flask(__name__)
#get the absolute directry of the server path for file uploads
APP_ROOT = os.path.dirname(os.path.abspath(__file__))
[further in the code]
#app.route("/create_staff", methods=["POST"])
def create_staff():
#define upload path
target = os.path.join(APP_ROOT, 'images/')
#check the folder exists, if it doesn't, create it
if not os.path.isdir(target):
os.mkdir(target)
print("PREPPING TO UPLOAD FILE \n")
f = request.files['file']
filename = f.filename
print(filename)
destination = "/".join([target, filename])
f.save(destination)
return redirect("/addstaff")
Any suggestions on how to troubleshoot this?
i had exact same issue, and not found the solution yet, but make sure that:
your input html tag has name='file' as this will refer to request.files['file']
your <form> tag is marked with enctype='multipart/form-data'
https://flask.palletsprojects.com/en/1.1.x/patterns/fileuploads/

Boto3 S3 NosuchKey error when downloading file

I am accessing the Project Gutenberg API and I wrote a Python program that creates a text file out of a randomly chosen book from the API. Since the txt file is different each time the document in the S3 bucket should be blank. I want to be able to store an object I can constantly write over in S3 then pull from it in Flask and put it on the user's computer.
So far I have been using boto3 and I set up an AWS account with a specific bucket. I loaded a trial .txt file in there but when the program is accessed now it only downloads the file I put in there with the specific text, it doesn't change based on my program like it should.
Boto seems to be throwing me for a loop so if there's another way I am open to it.
My code right now is a mess. I'm throwing everything I can at it to make it work but I know I've reach the point where I need some help.
from flask import Flask, render_template
from gutenberg.acquire import load_etext
from gutenberg.cleanup import strip_headers
import random
import os
from flask import send_from_directory
import boto3
from flask import Flask, request
from flask import Flask, Response
from boto3 import client
import botocore
app = Flask(__name__, static_url_path='/static')
def get_client():
return client(
's3',
'us-east-1',
aws_access_key_id='XXXXXXX',
aws_secret_access_key='XXXXXXX'
)
#app.route('/')
def welcome():
return 'Welcome to the server'
#app.route('/favicon.ico')
def favicon():
return send_from_directory(os.path.join(app.root_path, 'static'), 'favicon.ico', mimetype='image/vnd.microsoft.icon')
#app.route('/roulette', methods=['POST', 'GET'])
def roulette():
s3 = get_client()
f = open("GutProject.txt", "w")
file = s3.get_object(Bucket='book-roulette', Key='GutProject.txt')
for x in range(1):
y = (random.randint(0, 59000))
text = strip_headers(load_etext(y)).strip()
s3_client = boto3.client('s3')
open('GutProject.txt').write(text)
s3_client.upload_file('GutProject.txt', 'book-roulette', 'Gut-remote.txt')
s3_client.download_file('book-roulette', 'hello-remote.txt', 'hello2.txt')
print(open('hello2.txt').read())s3_client.download_file('MyBucket', 'hello-remote.txt', 'hello2.txt')
print(open('hello2.txt').read())
return Response(
file['Body'].read(),
mimetype='text/plain',
headers={"Content-Disposition": "attachment;filename=GutProject.txt"}
)
if __name__ == "__main__":
app.run(debug=True)
My app should let the user click a button on the URL page and it will download a random file to their computer. The HTML works great and the Python/Flask worked before but the file wasn't downloading (I'm on Heroku).
I keep getting these errors:
botocore.errorfactory.NoSuchKey
botocore.errorfactory.NoSuchKey: An error occurred (NoSuchKey) when calling the GetObject operation: The specified key does not exist.
If the error stems from the line: s3_client.download_file('book-roulette', 'hello-remote.txt', 'hello2.txt'), then the error NoSuchKey is trying to say it cannot find the file s3://book-roulette/hello-remote.txt in the s3 region you specify.
I would suggest checking that s3 path to make sure it exists, or that the specified bucket and key are correct.
Edit: I notice that you create the s3_client object within your loop and overwrite the one where you specify your region and credentials, so it's possible it might not be checking in the right region anymore, but that might result in an access denied error or bucket not found error instead

Flask in cPanel showing 404 for images under public folder

I have setup a Flask app in a cPanel server with CloudLinux. I used the Setup Python App feature.
The app is at a folder /home/user/app . The app URL is https://www.example.com/app
cPanel uses Phusion Passenger to make the app work with Apache.
When I created the app, a folder /home/user/app/public was created and supposedly all images should go there.
The app is working well, but all URLs to images in the public folder are giving 404 error. I've tried different urls like https://www.example.com/app/image.jpg, and https://www.example.com/app/public/image.jpg . Always 404.
This is the first time I am using this Setup Python App feature.
Does anyone know which is the right URL to use, or what needs to be configured in order for images to be served?
Thanks!
EDIT:
The image url is created using url_for:
return url_for('general.send_data_file', filename=key)
The generated url looks correct
I added a route to serve the files:
#general_blueprint.route('/public/data_store/data/<filename>', methods=['GET'])
def send_data_file(filename):
return send_from_directory(app.config.get('DATA_FOLDER'), filename)
I get 404 instead of the file.
The generated file url is /app/public/data_store/data/test.jpg for example.
The app runs under /app, and all created routes work and don't use the /app when defining the route. I added an app.logger.info call inside the send_data_file, and it is being called.
app.config.get['DATA_FOLDER'] equals ./public/data_store/data
No error in log from send_from_directory .
For serving static files outside your main static folder within your app you need to change that in Flask config like this:
app = Flask(__name__, static_folder='/home/user/app/public')
Then, use url_for as relative path with static as first parameter in your HTML file:
<img src="{{ url_for('static', filename='images/image.svg') }}" alt="svg image">

Download file on heroku

I have this simple function in my Flask app.
#app.route('/download')
#login_required
def download():
url="some_random_video_url_here"
re = requests.get(url)
with open("download/hello.mp4", 'wb') as file: #save hello.mp4 to download folder
file.write(re.content)
file.close()
flash("done downloading.")
return render_template('download.html')
When I run the app locally, the download function just run fine. But when I deploy the code to Heroku and access the url, I get 500 Internal Server Error
I think it has something to do with file system on Heroku but I don't know how to make this work. So how?

Categories