file upload from Flask template to external APIs - python

I have divided my flask app with two-part API (Flask API) and web app (Flask template).
From the web app, I am trying to upload a file but on the API side, I am not able to send.
File upload is working from APIs side, I have tested from the postman.
Template (UI with port: 3010) and API (port: 3009)
Below is running on API side with port 3009
#app.route('/sources', methods=['POST', 'GET'])
def upload_file():
if request.method == 'POST':
try:
print(request.form.get('file')) # Not able to print file here
print(request.form.get('Language1')) # I am able to print it
if 'file' not in request.files:
resp = jsonify({'message' : 'No file part in the request'})
resp.status_code = 400
return resp
file = request.files['file']
if file.filename == '':
resp = jsonify({'message' : 'No file selected for uploading'})
resp.status_code = 400
return resp
if file and allowed_file(file.filename,'sources'):
sourceFileName = secure_filename(file.filename)
Lang1 = request.form.get('Language1')
Lang2 = request.form.get('Language2')
except Exception as e:
print(e)
resp = jsonify({'message' : 'Server Error'})
resp.status_code = 500
return resp
Below is running on UI side with port 3010
#app.route('/sources', methods=['POST'])
def upload_sources():
if request.method == "POST":
Language1 = request.form["Language1"]
Language2 = request.form["Language2"]
file = request.files["file"]
# File object is printing here like: [<FileStorage: 'source_text.docx' ('application/vnd.openxmlformats-officedocument.wordprocessingml.document')>]
print(file)
params = {
"Language1":Language1,
"Language2":Language2,
"file":file
}
headers = {'content-type': 'application/json'}
req = requests.post('http://localhost:3009/sources', headers=headers, data=params)
r = req.json()
print(r['message']) # I am getting response message : ['No file part in the request']
return redirect(url_for('fetch_sources'))
Below is working fine, just fetching uploaded file
#app.route('/sources', methods=['GET'])
def fetch_sources():
sources = requests.get('http://localhost:3009/sources')
source_data = sources.json()
if source_data:
return render_template('sources.html', sources=source_data['sources'])

I was sending a file object and the way which I was following that was incorrect...
I can not send file directly to API from webapp.
Here I have changed my code and it is working fine.
if request.method == 'POST':
file = request.files["file"]
sourceFileName = secure_filename(file.filename)
cwd = os.getcwd()+'/'
if 'temp' not in os.listdir(cwd):
os.mkdir(cwd + 'temp')
file.save(os.path.join(cwd + 'temp', sourceFileName))
with open(cwd + 'temp/'+ sourceFileName, 'rb') as f:
data_file = ImmutableMultiDict([("file", f)])
resp = requests.post(api_base_url + "/sources",
files=data_file)

Related

How to display data in flask from post request on localhost? Error: local variable 'reqData' referenced before assignment

I want to display data that im sending in post request in the web browser on localhost:5000/event. In line print (reqData) data is displayed correctly in terminal when server is running, but server is rendering '/event' before i send a post and so reqData is not defined for that site.
post code
import requests
headers = {'content-type': 'application/json'}
payload = {'name': 'asd', 'sname': 'dsa'}
g = requests.post('http://localhost:5000/event', headers=headers, json=payload)
print(g.json)
flask code
#app.route('/event', methods=['GET', 'POST'])
def response():
if request.method=='POST':
reqData = request.get_json()
print(reqData)
return reqData
else:
if(reqData):
return reqData
else:
return 'No request.'
Simply change your post flask code by :
import requests
headers = {'content-type': 'application/json'}
payload = {'name': 'asd', 'sname': 'dsa'}
g = requests.post('http://localhost:5000/event', headers=headers, json=payload)
print(g.json()) # Line changed
Edit :
#app.route('/event', methods=['GET', 'POST'])
def response():
if request.method=='POST':
reqData = request.get_json()
print(reqData)
return reqData
else:
try: # Adding try except works
if(reqData):
return reqData
except:
return 'No request.'

github v3 api delete public key return error {'message': 'Not Found', 'documentation_url': 'https://developer.github.com/v3'}

I'm using python3 requests module to access Github v3 API (DELETE /user/keys/:key_id) of the deleting public ssh-key that it return the error
{'message': 'Not Found''documentation_url':'https://developer.github.com/v3'}.
I use python3 virtual environmemt and requests module to handle.
I checked the URL and method of the api and it has no problem. In addition, I added access_token='My token' after the URL parameter. but no effect. i try to use command
curl -H "Authorization: token 93ca7d685602dca9d32e8788ddffafc8e7385003" https://api.github.com/users/codertocat -I to find the scope of the token.
and I checked that the the key_id is correct also.
def __init__(self):
self.accessToken = '93ca7d685602dca9d32e8788ddffafc8e7385003'
self.rootUrl = 'https://api.github.com'
self.headers = {"Authorization": "token %s" % self.accessToken}
def baseGet(self, url, me='get', data=None):
try:
response = ''
if me == 'get':
response = requests.get(url)
if me == 'post':
response = requests.get(url, data)
if me == 'delete':
response = requests.delete(url)
else:
print('no support')
try:
data = response.json()
except:
data = response.content
return data
except Exception as e:
print('error by', e)
return False
def del_user_public_key(self, key_id):
# del_user_public_key
userkey = self.rootUrl + '/users/keys/%d?access_token=%s' % (key_id, self.accessToken)
print(userkey)
return self.baseGet(userkey, me='delete')
I expect the output of the result to be Status 204 No Content and the public deleted in github.

youtube-dl front-end Video Download - using python and flask?

How to download youtube and other website video and audio file through youtube-dl (Front-End download - WEB UI)
Search and download the video through frontend.
i have write a script is python and flask -
from flask import (
Flask, Response,
render_template,
request,
redirect,
flash,
url_for,
send_file,
session,
)
import subprocess
from ydl import get_media, verify, fetch_name
from zipper import zipping
import os
app = Flask(__name__)
app.secret_key = "supposed to be a secret"
#app.route("/return-file/")
def return_file():
import pdb
#pdb.set_trace()
num_choice = session.get("choice")
filename = session.get("filename")
url = session.get("url")
if num_choice == 1:
filename_formatted = filename + ".mp3"
location = "media/Audio downloads/{}.mp3".format(session.get("id"))
if num_choice == 2:
#filename_formatted = filename + ".mp4"
#cc = get_media(url, num_choice)
print(url)
print('==============================================================================')
#"youtube-dl", "--get-url", url
#subprocess.run(["youtube-dl", "--no-check-certificate", "--get-url", url])
#subprocess.run(["youtube-dl", "--no-check-certificate", url])
test = subprocess.run(["youtube-dl", "--no-check-certificate", "--get-filename", url])
print(test)
csv = '1,2,3\n4,5,6\n'
return Response(
csv,
mimetype="text/csv",
headers={"Content-disposition":
"attachment; filename=test"})
#return send_file('', attachment_filename="myplot.csv")
print('==============================================================================')
#subprocess.run(["youtube-dl", "--no-check-certificate", url])
#location = "media/{}.mp4".format(session.get("id"))
#if os.path.isdir(location):
#print('True')
if num_choice == 3 or num_choice == 4:
filename_formatted = filename + ".zip"
location = "media/{}.zip".format(session.get("id"))
#return send_file(
#location, attachment_filename=filename_formatted, as_attachment=True
#)
#app.route("/", methods=["GET", "POST"])
def home_page():
"""
Displaying homepage
"""
title = "YDL | YouTube Downloader"
if request.method == "POST":
attempted_url = request.form["url"]
attempted_choice = int(request.form["submit"])
title = [attempted_url, attempted_choice]
if attempted_url != "":
if verify(attempted_url):
result_id = get_media(attempted_url, attempted_choice)
session["url"] = attempted_url
session["id"] = result_id
session["choice"] = attempted_choice
filename = fetch_name(attempted_url)
session["filename"] = filename
# return render_template('material-life.html', title = "Success {}".format(title))
# return render_template('material-life.html', title = result_id)
return redirect(url_for("return_file"))
else:
return render_template(
"material-life.html", title="YDL | Doesn't belong to YouTube"
)
else:
return render_template(
"material-life.html", title="YDL | URL shouldn't be empty"
)
return render_template("material-life.html", title=title)
#app.errorhandler(404)
def page_not_found(error):
"""
for anyone trying different links or searching for images within the server
"""
return (
render_template(
"error_template.html",
title="404 bud",
message="Time to make the chimi-fuckin'-changas. ",
subline="404, not there",
image_location=url_for("static", filename="images/deadpool-funny.jpg"),
),
404,
)
#app.errorhandler(400)
def bad_request(error):
"""
For handling situations where the server doesn't know what to do with the browser's request
"""
return (
render_template(
"error_template.html",
title="Aaaah ...",
message="나는 이해하지 못한다.",
subline="Yeah, the server couldn't understand what you asked for, Sorry",
image_location=url_for("static", filename="images/simpson-gangam.jpg"),
),
400,
)
if __name__ == "__main__":
app.run(debug=True)
its working on console base download... but i want to download through front end... without save - direct download
You can use pytube module, which depends on youtube-dl.
You seem to be building an app, but with the video's url, you can use the below one-liner to download the video:
from pytube import YouTube
YouTube(video_url).streams.first().download(filename='file_name')

Tweets streaming to .txt file with Python

I have the below code and want to write the stream of tweets to a text file. Is there a way to include the output to text file within the same code and save it in the working directory? I am an IDE lover and really don't like using the console. I am new to python (2 weeks), I am an R / R Studio user.
I know I could use:
filename.py > output.txt
I am currently using Rodeo, Python 3.6.1.
import oauth2 as oauth
import urllib.request as urllib
api_key = "##"
api_secret = "##"
access_token_key = "##-##"
access_token_secret = "##"
_debug = 0
oauth_token = oauth.Token(key=access_token_key, secret=access_token_secret)
oauth_consumer = oauth.Consumer(key=api_key, secret=api_secret)
signature_method_hmac_sha1 = oauth.SignatureMethod_HMAC_SHA1()
http_method = "GET"
http_handler = urllib.HTTPHandler(debuglevel=_debug)
https_handler = urllib.HTTPSHandler(debuglevel=_debug)
'''
Construct, sign, and open a twitter request
using the hard-coded credentials above.
'''
def twitterreq(url, method, parameters):
req = oauth.Request.from_consumer_and_token(oauth_consumer,
token=oauth_token,
http_method=http_method,
http_url=url,
parameters=parameters)
req.sign_request(signature_method_hmac_sha1, oauth_consumer, oauth_token)
headers = req.to_header()
if http_method == "POST":
encoded_post_data = req.to_postdata()
else:
encoded_post_data = None
url = req.to_url()
opener = urllib.OpenerDirector()
opener.add_handler(http_handler)
opener.add_handler(https_handler)
response = opener.open(url, encoded_post_data)
f = open("output.txt", "wb")
def fetchsamples():
url = "https://stream.twitter.com/1.1/statuses/sample.json"
parameters = []
response = twitterreq(url, "GET", parameters)
for line in response:
f.write(line)
if __name__ == '__main__':
fetchsamples()
# f.close()
Besides the comment I made previously, I would suggesting checking out this stack overflow question: how to direct output into a txt file in python in windows
To quote:
If you want to do it in Python then you would write:
with open('out.txt', 'w') as f:
f.write(something)`
Obviously this is just a trivial example. You'd clearly do more inside the with block.

unable to detect request content_type

On a django server, I process uploaded zip files sent from a python script. But I am getting "" (a blank string) for file.content_type. What am I doing wrong?
#csrf_exempt
def Import( request ):
if request.method != 'POST':
return HttpResponseNotAllowed('Only POST here')
if not request.FILES or not request.FILES.get( u'file' ):
return HttpResponse('Must upload a file')
file = request.FILES[u'file']
if file.content_type == 'application/zip':
unzipped_dir = unzip_file( file )
uid = create_project( unzipped_dir )
shutil.rmtree( unzipped_dir )
py_ob = { }
py_ob['success'] = uid is not None
if uid is not None:
py_ob['id'] = uid
json_ob = simplejson.dumps(py_ob)
return HttpResponse( json_ob, mimetype="application/json" )
else:
return HttpResponseNotAllowed( 'Only POST zip files here' )
This is the script which sends the zip file up:
import sys
import os
import requests
if len (sys.argv) < 5:
print "pass in url, username, password, file"
else:
url = sys.argv[1]
username = sys.argv[2]
password = sys.argv[3]
phile = sys.argv[4]
if os.path.exists(phile):
files = {'file': open( phile, 'rb' )}
r = requests.post( url, files=files, auth=( username, password ) )
if r.status_code == 200:
json_response = r.json()
if json_response['success']:
print "id: " + str( json_response['id'] )
else:
print "failure in processing bundle"
else:
print "server problem: " + str(r.status_code)
print r.text
else:
print "cannot find file to upload"
The Content-Type header is completely arbitrary (and optional) and not a good way to detect whether or not you're dealing with a valid ZIP file. Have you made sure your browser is supplying it?
Django's documentation tells us the same:
UploadedFile.content_type
The content-type header uploaded with the file (e.g. text/plain or application/pdf). Like any data supplied by the user, you shouldn’t
trust that the uploaded file is actually this type. You’ll still need
to validate that the file contains the content that the content-type
header claims – “trust but verify.”
You should be using zipfile.is_zipfile instead.

Categories