How to process the file which is uploaded by giving the file path to the python script and download the processed file ?
The code
#app.route("/upload", methods=['POST'])
def upload():
target = os.path.join(APP__ROOT, 'data/')
print(target)
if not os.path.isdir(target):
os.mkdir(target)
for file in request.files.getlist("file"):
filename = file.filename
print(filename)
destination = "/".join([target, filename])
print(destination)
file.save(destination)
return render_template("downloads.html")
You need to return the file.
response = app.make_response(file)
response.headers["Content-Disposition"] = "attachment; filename=yourfile.csv"
return response
Related
I have an API to upload files in my flask application. It's uploading the file perfectly fine but when I try to get the file using the path of url which I got from my api, I am getting 404 file not found.
Here is my code.
app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = 'uploads'
def generate_unique_filename(filename):
_, ext = os.path.splitext(filename)
unique_filename = f"{uuid.uuid4().hex}{ext}"
path = os.path.join(app.config['UPLOAD_FOLDER'], unique_filename)
return unique_filename, path
#app.route('/upload', methods=['POST'])
def upload_file():
file = request.files['file']
if file:
filename, path = generate_unique_filename(file.filename)
file.save(path)
file_url = f"{request.host_url}{app.config['UPLOAD_FOLDER']}/{filename}"
return jsonify({'file_url': file_url}), 201
else:
return jsonify({'error': 'No file was uploaded.'}), 400
I want to get url of my uploaded file from my api that can be opened.
from PIL import Image
import PyPDF2
tess.pytesseract.tesseract_cmd = r'C:\Users\szaid\AppData\Local\Programs\Tesseract-OCR\tesseract'
translator=Translator()
project_dir = os.path.dirname(os.path.abspath(__file__))
app = Flask(__name__,
static_url_path='',
static_folder='static',
template_folder='template')
photos = UploadSet('photos', IMAGES)
pdf = UploadSet('pdf', DOCUMENTS)
app.config['DEBUG'] = True
app.config['UPLOAD_FOLDER']= 'images'
class Get(object):
def __init__(self, file): enter code here
if render_template('image.html'):
self.file = tess.image_to_string(Image.open(project_dir + '/images/'+ file))
elif render_template('pdf.html'):
self.file = PyPDF2.PdfFileReader(project_dir+'/pdff/'+ file)
And below, this is backend code to save the file in 'images' folder but its giving me an error.
I mean there is two different html pages and in both pages, there is an option to upload file and image. but dont know how to manage in flask...
#app.route('/pdf', methods=["GET","POST"])
def pdf():
if request.method == 'POST':
if 'pdf' not in request.files:
return 'there is no photo'
name1 = request.form['pdf-name'] + '.pdf'
pdf = request.files['pdf']
path = os.path.join(app.config['UPLOAD_FOLDER'], name1)
pdf.save(path)
TextObject = Get(name1)
return TextObject.file
return render_template('pdf.html')
error
You're getting this error because your path to the PDF file is wrong. You've added the file extension but the path is missing the file name. You also have a problem with your slashes in the path. A correct path would be like:
"D:\images\yourFileName.pdf"
Here is my sample code:
The problem is it returns a downloadable zip file but the file is corrupted/ has error. I checked the file by manually opening it in a folder and it works. I think the problem here is passing the zip file from backend to cherrypy. Or how do I convert the zip file into a file type?
cherrypy.response.headers['Content-Type'] = "'Content-Type', 'application/zip'"
cherrypy.response.headers['Content-Disposition'] = ('attachment; filename=' +
name.format(fname=name))
export_file = str(response["message_data"]["file"])
return export_file
Creating ZIP File
zipf = zipfile.ZipFile(full_directory + '.zip', 'w', zipfile.ZIP_DEFLATED)
for root, dirs, files in os.walk(full_directory + '/'):
for file in files:
zipf.write(os.path.join(root, file), arcname=file)
zipf.close()
file_upload = open(full_directory + '.zip', "r")
Passing ZIP File to CherryPy:
response_json["message_data"]["file"] = file_upload
response_json["message_data"]["name"] = file_name
Here is how I do to generate ZIP and download it from a server, it works well in local development.
import zipfile
doc = get_object_or_404(Document,id=id_obj)
filepath = doc.file.path
filename = os.path.basename(doc.file.name)
directory = os.path.dirname(filepath)
xzip = zipfile.ZipFile(os.path.join(directory,"%s.zip" % filename), "w")
xzip.write(filepath,filename)
xzip.close()
zip_file = open(xzip.filename, 'rb')
response = HttpResponse(zip_file, content_type='application/zip')
response['Content-Disposition'] = 'attachment; filename="%s.zip"' %
os.path.splitext(filename)[0]
return response
All my static & media files are uploaded to AWS in production. So I change a little bit
# filepath becomes
filepath = settings.MEDIA_ROOT + "/" + doc.file.name
But When I try to download it, it gives me [Errno 2] No such file or directorywith the link:
https://bucket_name.s3.amazonaws.com/media/public/files/file.pdf.zip
the settings.MEDIA_ROOT is:
AWS_ACCESS_KEY_ID = config('AWS_ACCESS_KEY_ID')
AWS_SECRET_ACCESS_KEY = config('AWS_SECRET_ACCESS_KEY')
AWS_STORAGE_BUCKET_NAME = 'bucket_name'
AWS_S3_CUSTOM_DOMAIN = '%s.s3.amazonaws.com' % AWS_STORAGE_BUCKET_NAME
AWS_PUBLIC_MEDIA_LOCATION = 'media/public'
MEDIA_ROOT = "https://%s/%s/" % (AWS_S3_CUSTOM_DOMAIN, AWS_PUBLIC_MEDIA_LOCATION)
doc.file.path gives me the error: 'This backend doesn't support absolute paths', that's why I changed to MEDIA_ROOT + doc.file.name
How to do that to download from AWS the zip file generated?
The file exists on S3, not the local file system. When you call those os.path.* functions the code is trying to find the file on the local file system. It's giving you that error because that S3 URL you are giving it as the path can't be mapped to anything on the local file system.
Why don't you allow S3 to serve the file directly to the end-user's browser by simply return a redirect response with the URL of the S3 file instead of trying to read the file and return the contents in the response?
The problem is that I have an HTML form that is generated dynamically, therefore I don't know how many file/text inputs are going to be there. So I decided not to use a form and handle file upload through request.FILES.
This is my code so far.
elif request.method == "POST":
for ta in text_attachments:
ta.text = request.POST["text-" + ta.id.__str__()]
ta.save()
for fa in text_attachments:
if request.FILES.get("file-" + fa.id.__str__(), None):
# fa.file = request.FILES["file-" + fa.id.__str__()]
handle_uploaded_file(fa, request.FILES["file-" + fa.id.__str__()])
fa.save()
And this is the handle_uploaded_file function:
def handle_uploaded_file(instance, f):
path = coopertaion_attachment_path(instance, f.name)
with open(path, 'wb+') as destination:
for chunk in f.chunks():
destination.write(chunk)
And this is the function that decides where the file should be uploaded.
def coopertaion_attachment_path(instance, filename):
print("Filename: " + filename)
os.umask(0)
path = 'applications/cooperation/%s/' % instance.application.user.id
att_path = os.path.join(settings.MEDIA_ROOT, path)
if settings.DEFAULT_FILE_STORAGE == "django.core.files.storage.FileSystemStorage":
if not os.path.exists(att_path):
os.makedirs(att_path, 0o777)
print("Creating path...")
return os.path.join(path, filename)
In the end I always get this error:
[Errno 2] No such file or directory: 'applications/cooperation/1/filename.pdf'
Is it even possible to handle uploaded files without django form? How do I assign the uploaded file to a FileField of one of my models?
You seem to be doing it right (file uploading and handling). Problem is in your cooperation_attachment_path method. You are returning os.path.join(path, filename) where path holds relative to your project path which does not exist hence the error.
[Errno 2] No such file or directory:
'applications/cooperation/1/filename.pdf'
att_path holds absolute path so you should do:
return os.path.join(att_path, filename)