i'm trying to upload an image to a server (pythonanywhere.com) with a python script using web2py, so i can make some changes to the image and save it...i will use the script in a terminal and upload the image via curl like that:
curl -i -F filedata=#image.jpg http://my_username.pythonanywhere.com/DocScanner/default/upload
That's build in to the web2py SQLFORM. Add an upload field and web2py will stream the file to disk with a safe name and it will return the name to your code. Have a look at the web2py book which documents SQLFORM and upload fields.
import os
def decode_image3(src):
import base64
import re
import uuid
result = re.search("data:image/(?P<ext>.*?);base64,(?P<data>.*)", src, re.DOTALL)
if result:
ext = result.groupdict().get("ext")
data = result.groupdict().get("data")
else:
raise Exception("Do not parse!")
# 2, base64 decoding
img = base64.urlsafe_b64decode(data)
# 3, the binary file is saved
filename = "{}.{}".format(uuid.uuid4(), ext)
completeName = os.path.join(request.folder,'uploads', filename)
with open(completeName, "wb") as f:
f.write(img)
return filename
#request.restful()
def Image2():
response.view = 'generic.json'
def POST(**vars):
image = decode_image3(request.vars.image)
completeName = os.path.join(request.folder,'uploads', image)
stream = open(completeName, 'rb')
if os.path.exists(completeName):
rv = os.remove(completeName)
save = db.test.insert(image=stream, age=34)
return dict(msg=save)
return locals()
Related
I am having an issue trying to download download in-memory ZIP-FILE object using Flask send_file. my zip exists in memory and is full of text documents but when I try with this code
the result I get is: it downloads like it is supposed to but it downloads an empty zip file! it's like it is copying nothing ... I have no idea how to solve this problem.
#app.route('/downloads/', methods=['GET'])
def download():
from flask import send_file
import io
import zipfile
import time
FILEPATH = r"C:\Users\JD\Downloads\trydownload.zip"
fileobj = io.BytesIO()
with zipfile.ZipFile(fileobj, 'w') as zip_file:
zip_info = zipfile.ZipInfo(FILEPATH)
zip_info.date_time = time.localtime(time.time())[:6]
zip_info.compress_type = zipfile.ZIP_DEFLATED
with open(FILEPATH, 'rb') as fd:
zip_file.writestr(zip_info, fd.read())
fileobj.seek(0)
return send_file(fileobj, mimetype='zip', as_attachment=True,
attachment_filename='%s.zip' % os.path.basename(FILEPATH))
I had the exact same issue with the Flask send_file method.
Details:
Flask version 2.0.1
OS: Windows 10
Solution
I figured out a workaround to this i.e. instead of the send_file method, this can be done by returning a Response object with the data. Replace the return statement in your code with the following and this should work.
#app.route('/downloads/', methods=['GET'])
def download():
from flask import Response # Changed line
import io
import zipfile
import time
FILEPATH = r"C:\Users\JD\Downloads\trydownload.zip"
fileobj = io.BytesIO()
with zipfile.ZipFile(fileobj, 'w') as zip_file:
zip_info = zipfile.ZipInfo(FILEPATH)
zip_info.date_time = time.localtime(time.time())[:6]
zip_info.compress_type = zipfile.ZIP_DEFLATED
with open(FILEPATH, 'rb') as fd:
zip_file.writestr(zip_info, fd.read())
fileobj.seek(0)
# Changed line below
return Response(fileobj.getvalue(),
mimetype='application/zip',
headers={'Content-Disposition': 'attachment;filename=your_filename.zip'})
I am developing API using Flask-restplus. One of the endpoints handles audio file uploads which can be either mp3 or wav format. According to PUT request to upload a file not working in Flask, file uploaded by put is in either request.data or request.stream. So this is what I did:
#ns.route('/upload')
class AudioUpload(Resource):
def put(self):
now = datetime.now()
filename = now.strftime("%Y%m%d_%H%M%S") + ".mp3"
cwd = os.getcwd()
filepath = os.path.join(cwd, filename)
with open(filepath, 'wb') as f:
f.write(request.stream.read())
return filepath
I am saving the file as mp3. However sometime the file comes in as wav. Is there a way to get the original file name from put request in the similar way as post request:
file = request.files['file']
filename = file.filename
So i am currently creating a text file from a jinja2 template on the fly and having it be downloaded by the users browser, however i want to add an option to send it somewhere via FTP (all the FTP details are predefined and wont change)
how do i create the file to be sent?
Thanks
code:
...
device_config.stream(
STR = hostname,
IP = subnet,
BGPASNO = bgp_as,
LOIP = lo1,
DSLUSER = dsl_user,
DSLPASS = dsl_pass,
Date = install_date,
).dump(config_file)
content = config_file.getvalue()
content_type = 'text/plain'
content_disposition = 'attachment; filename=%s' % (file_name)
response = None
if type == 'FILE':
response = HttpResponse(content, content_type=content_type)
response['Content-Disposition'] = content_disposition
elif type == 'FTP':
with tempfile.NamedTemporaryFile() as temp:
temp.write(content)
temp.seek(0)
filename = temp.name
session = ftplib.FTP('192.168.1.1','test','password')
session.storbinary('STOR {0}'.format(file_name), temp)
session.quit()
temp.flush()
return response
EDIT
needed to add temp.seek(0) before sending the file
You can use the tempfile module to create a named temporary file.
import tempfile
with tempfile.NamedTemporaryFile() as temp:
temp.write(content)
temp.flush()
filename = temp.name
session.storbinary('STOR {0}'.format(file_name), temp)
Here is a working example using BytesIO under io module. Code is tested and works.
import ftplib
import io
session = ftplib.FTP('192.168.1.1','USERNAME','PASSWORD')
# session.set_debuglevel(2)
buf=io.BytesIO()
# b'str' to content of buff.write() as it throws an error in python3.7
buf.write(b"test string")
buf.seek(0)
session.storbinary("STOR testfile.txt",buf)
session.quit()
I have a Django app in which when I click on the link then I can download a .txt file. Now instead of downloading that file I need to open that file (in 'r' mode). I'm trying to do something similar to that of mail attachments that is when we click on the attachment then it opens up instead of downloading. How can I do it ? The following code is to download the .txt file :
def fetch_logfile(request,logfile):
try:
folder,log,_ = logfile.split("/")
pathRelative = r"/LogFile/"+log
folder,log,_ = logfile.split("/")
pathRelative = r"/LogFile/"+log
path = pathRelative[1::]
os.startfile(pathRelative,open)
file_path =os.getcwd()+ '/' +pathRelative
file_wrapper = FileWrapper(file(file_path,'rb'))
file_mimetype = mimetypes.guess_type(file_path)
response = HttpResponse(file_wrapper, content_type=file_mimetype )
response['X-Sendfile'] = file_path
response['Content-Length'] = os.stat(file_path).st_size
nameOnly = log.split('/')
response['Content-Disposition'] = 'attachment; filename=%s' % nameOnly[len(nameOnly)-1]
return response
except:
## do something else
The following code works which I have tried in Python IDLE but when I try the same in Django then it doesn't work. I'm not sure if this is the right way either.Please advice me on this.
def fetch_Logfile(request,logfile):
import os,sys
path = "C:\\Users\\welcome\\Desktop\\mysite\\LogFile\\"+"756849.txt"
os.startfile(path,open)
## do something with logfile and request
def fetch_Logfile(request,logfile):
path = "C:\\Users\\welcome\\Desktop\\mysite\\LogFile\\"+"756849.txt"
import webbrowser
webbrowser.open(path)
## do something with logfile and request
def fetch_Logfile(request,logfile):
import win32api,os,subprocess
path = "C:\\Users\\welcome\\Desktop\\mysite\\LogFile\\"+"756849.txt"
filename_short = win32api.GetShortPathName(path)
subprocess.Popen('start ' + filename_short, shell=True )
subprocess.Popen('start ' + path, shell=True )
## do something with logfile and request
my_file = open(file_path, 'r')
response = HttpResponse(my_file.read(), mimetype='text/plain')
response['Content-Disposition'] = 'inline;filename=some_file.txt'
return response
Here is the MIME Types – Complete List
You can provide mimetype = ' / ' based on the file extension by referencing the mime type list.
I am using a script to strip exif data from uploaded JPGs in Python, before writing them to disk. I'm using Flask, and the file is brought in through requests
file = request.files['file']
strip the exif data, and then save it
f = open(file)
image = f.read()
f.close()
outputimage = stripExif(image)
f = ('output.jpg', 'w')
f.write(outputimage)
f.close()
f.save(os.path.join(app.config['IMAGE_FOLDER'], filename))
Open isn't working because it only takes a string as an argument, and if I try to just set f=file, it throws an error about tuple objects not having a write attribute. How can I pass the current file into this function before it is read?
file is a FileStorage, described in http://werkzeug.pocoo.org/docs/datastructures/#werkzeug.datastructures.FileStorage
As the doc says, stream represents the stream of data for this file, usually under the form of a pointer to a temporary file, and most function are proxied.
You probably can do something like:
file = request.files['file']
image = file.read()
outputimage = stripExif(image)
f = open(os.path.join(app.config['IMAGE_FOLDER'], 'output.jpg'), 'w')
f.write(outputimage)
f.close()
Try the io package, which has a BufferedReader(), ala:
import io
f = io.BufferedReader(request.files['file'])
...
file = request.files['file']
image = stripExif(file.read())
file.close()
filename = 'whatever' # maybe you want to use request.files['file'].filename
dest_path = os.path.join(app.config['IMAGE_FOLDER'], filename)
with open(dest_path, 'wb') as f:
f.write(image)