Getting the absolute filename of file uploaded through Python Flask App - python-3.x

I am trying to create a flask app that can be used to upload any user selected file to my azure storage. For some reason, the mime-type of the uploaded file is always set to 'application/octet-stream'. If I directly upload the file to azure using its UI, then the mime-type is correct. To solve this problem, I am trying to manually calculate the mimetype of the file and pass it as metadata.
The issue I am having is that I am not able to figure out a way to get the absolute filepath of the user selected file to be uploaded.
What I am looking for is the absolute path: path/to/file/doctest2.txt
Here is how the flask app looks like:
#app.route('/', methods=['GET', 'POST'])
def upload_file():
if request.method == 'POST':
file = request.files['file']
filename = secure_filename(file.filename)
fileextension = filename.rsplit('.',1)[1]
Randomfilename = id_generator()
filename = Randomfilename + '.' + fileextension
try:
blob_service.create_blob_from_stream(container, filename, file)
except Exception:
print 'Exception=' + Exception
pass
ref = 'http://'+ account + '.blob.core.windows.net/' + container + '/' + filename
seems like we can get the filename using f.filename, but I am not sure how to get the full path here.
Complete code can be found here:
https://github.com/codesagar/Azure-Blobs/blob/master/blob.py
The ultimate goal is to calculate the mimetype of the file to be uploaded.
I do have the file-blob(variable f). IS there a better way to get the mime from blob rather than hunting for the absolute file-path?

I solved my problem by using the following line of code:
mime_type = f.content_type
This gives me the mimetype of the file and eliminates the need for getting the file's absolute path.

Related

How to get filename from a file object in PYTHON?

I am using below code where I am using PUT api from POSTMAN to send a file to a machine hosting the api using python script
#app.route('/uploadFIle', methods=['PUT'])
def uploadFile():
chunk_size = 4096
with open("/Users/xyz/Documents/filename", 'wb') as f:
while True:
chunk = request.stream.read(chunk_size)
if len(chunk) == 0:
break
f.write(chunk)
return jsonify({"success":"File transfer initiated"})
Is there a way to get the original filename so that I can use the same while saving the file ?
Can do as below by passing name from PUT api itself, but is it the best solution ?
#app.route('/uploadFIle/<string:filename>', methods=['PUT'])
def uploadFile(filename):
Below is how I achieved it using flask -
Choose form-data under body in POSTMAN
You can give any key, i used 'file' as key, then choose option 'file' from drop down arrow in key column
Attach file under 'value' column and use below code to get the file name -
from flask import request
file = request.files['file']
file_name = file.filename

Download pdf file(Not restricted) from google drive through URL

import os
import requests
def download_file(download_url: str, filename: str):
"""
Download resume pdf file from storage
#param download_url: URL of reusme to be downloaded
#type download_url: str
#param filename: Name and location of file to be stored
#type filename: str
#return: None
#rtype: None
"""
file_request = requests.get(download_url)
with open(f'{filename}.pdf', 'wb+') as file:
file.write(file_request.content)
cand_id = "101"
time_current = "801"
file_location = f"{cand_id}_{time_current}"
download_file("https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf", file_location)
cand_id = "201"
time_current = "901"
download_file("https://drive.google.com/file/d/0B1HXnM1lBuoqMzVhZjcwNTAtZWI5OS00ZDg3LWEyMzktNzZmYWY2Y2NhNWQx/view?hl=en&resourcekey=0-5DqnTtXPFvySMiWstuAYdA", file_location)
----------
First file is working perfectly fine (i.e. 101_801.pdf)
But Second one is not able to open in any pdf reader(i.e.
201_901.pdf)(Error: We can't open this file).
What I understood is I'm not able properly read and write for file
from drive which is open for all. How to read that file and write?
I can use google drive API but can we have better solution without
using that ?
I tried out the code and couldnt open the PDF file as well. I suggest trying out gdown package. It is easy to use and you can download even large files from google drive. I used it in my class to download .sql db files (+-20Gb) for my assignments.
If you want to build more on this code, then you should probably check out Drive API. It is a well documented fast API.
I was able to find the solution for it through wget in python. Answering it so that it could help someone in the future.
import os
import wget
def download_candidate_resume(email: str, resume_url: str):
"""
This function is used to download resume from google drive and store on the local system
#param email: candidate email
#type email: str
#param resume_url: url of resume on google drive
#type resume_url: str
"""
file_extension = "pdf"
current_time = datetime.now()
file_name = f'{email}_{int(current_time.timestamp())}.{file_extension}'
temp_file_path = os.path.join(
os.getcwd(),
f'{email}_{int(current_time.timestamp())}.{file_extension}',
)
downloadable_resume_url = re.sub(
r"https://drive\.google\.com/file/d/(.*?)/.*?\?usp=sharing",
r"https://drive.google.com/uc?export=download&id=\1",
resume_url,
)
wget.download(downloadable_resume_url, out=temp_file_path)

Why Reading Upload file and Reading Local file producing different results?

I am posting file to python flask and then read its content using following code:
def post(self):
if 'file' not in request.files:
return {'error': 'no file'}
try:
f=open("text2.txt")
local_content=f.read()
content=request.files['file'].read().decode('utf-8')
if hash(content) != hash(local_content) :
return {'error': 'content changed','local':hash(local_content),'uploaded':hash(content)}
else:
return {'error': 'same','local':hash(local_content),'uploaded':hash(content)}
I also put same file text2.txt on server and read it locally using
local_content=f.read()
but both results are different.I tried comparing two string using following
if content != local_content
above conditions is always returning true.
but when I print both strings they are exactly same.
I am doing some processing on those strings and trying and both content and local_content produces different results.
So can anyone tell me why uploaded content is behaving differently than local content
Even I face this issue while uploading images using flask. The binary streams were different as compared to reading local file.
I solve this issue with file.seek(0)
files = request.files.getlist('files[]')
for file in files:
file.seek(0)
fileBytes = file.read()
image_stringRead = base64.b64encode(fileBytes)

Jira rest api get issue attachment via python

So, I need to download attachments to the issue in Jira using python. I have next code
from atlassian import Jira
issue = jira.issue(issuekey, fields='summary,comment,attachment')
for attachment in issue['fields']['attachment']:
with open((attachment.filename), 'wb') as file:
file.write(attachment.get(b'', b''))
After running the code I'm getting 3 empty files(txt, png, png) without any data inside..
How can I get(download) files from issue to my current folder?
Try using expand="attachment"
Ex:
issue = jira.issue(issuekey, expand="attachment")
for attachment in issue['fields']['attachment']:
with open(attachment.filename, 'wb') as file:
file.write(attachment.get())
You need the link to the contents of the attachment which is stored under the key 'content'. Then just use .get() request, that is in Jira library:
for attachment in issue['fields']['attachment']:
link = attachment['content']
link = link.split("https://jira.companyname.com/")[1]
b_str = jira.get(link, not_json_response=True)
with open((attachment['filename']), 'wb') as file:
file.write(b_str)
Notice that you need to trim the link, because jira.get() automatically includes the domain to the request url.
Get the attachment details:
get the jira attachment file URL
download the file using Request Module.
Check the file in file list.
issue = jira.issue(jira_ticket, expand='changelog')
attach = issue.fields.attachment
file_url = attach[0].content
file_path = "filename"
r = requests.get(file_url, auth=('jira_user', 'jira_pass'))
with open(file_path, 'wb') as f:
f.write(r.content)

Validate and save a ZIP file in Flask

I'm writing an app using Flask and one of the things I want in it is the ability to upload a ZIP that conforms to a specific form; as such I have a small function that takes a FileStorage object from the form and first unzips it, checks the contents, and then tries to save. There's a problem, however - apparently unzipping it "breaks" the FileStorage object, as the following function:
def upload_modfile(modfile):
if not modfile.filename.endswith('.zip'):
raise ModError('Incorrect filename')
mod_path = join(get_mods_path(), secure_filename(modfile.filename))
if isfile(mod_path):
raise ModError('File ' + modfile.filename + ' already exists')
modzip = ZipFile(modfile)
base_filename = modfile.filename[:-4]
modzip_contents = modzip.namelist()
if join(base_filename, 'info.json') not in modzip_contents:
raise ModError('Could not validate file')
modfile.save(mod_path)
return True
saves modfile as a text file saying Archive: <filename>.zip. If I comment out the entire ZipFile bit (i.e. everything involving modzip), the file is saved just fine.
I'm pretty much brand new to Python and am a little confused as to what to do in this case, save for saving the file in /tmp. Should I somehow clone modfile by way of some stream? Is there a way of "rewinding" the stream pointer within FileStorage that I'm missing?

Resources