i am creating pdf from html and it gets converted but without image. i have tried the absolute urls also but it still doesn't work
pdf function:
def test_pdf(request):
template = get_template('../templates/index.html')
html = template.render(Context(data))
filename = 'pdfs/'+str(random.random())+'.pdf'
file = open(filename, "w+b")
pisaStatus = pisa.CreatePDF(html.encode('utf-8'), dest=file, encoding='utf-8',link_callback=link_callback)
# Return PDF document through a Django HTTP response
file.seek(0)
pdf = file.read()
file.close() # Don't forget to close the file handle
return HttpResponse({"success":"success"})
def link_callback(uri, rel):
sUrl = settings.STATIC_URL # Typically /static/
sRoot = settings.STATIC_ROOT # Typically /home/userX/project_static/
mUrl = settings.MEDIA_URL # Typically /static/media/
mRoot = settings.MEDIA_ROOT # Typically /home/userX/project_static/media/
if uri.startswith(mUrl):
path = os.path.join(mRoot, uri.replace(mUrl, ""))
elif uri.startswith(sUrl):
path = os.path.join(sRoot, uri.replace(sUrl, ""))
else:
return uri # handle absolute uri (ie: http://some.tld/foo.png)
if not os.path.isfile(path):
raise Exception(
'media URI must start with %s or %s' % (sUrl, mUrl)
)
return path
settings file :
PROJECT_ROOT = "/var/www/html/newclone/userapi/"
MEDIA_ROOT = path.join(PROJECT_ROOT,'media')
MEDIA_URL = '/media/'
STATIC_ROOT = path.join(PROJECT_ROOT,'static-root')
STATIC_URL = "/static/"
What is wrong in this. pdf is generated successfully but the images are missing
html file :
<div class="h1"><img src="/media/xyz"></div>
Could not even imagine the error :
in my css i have written :
.main{width:75%;}
because of this images were not visible. I just removed it randomly and images started displaying
Related
So here is my issue:
def get_datasheets(self, build_id):
catalog = self._get_catalogue(build_id)
paths = []
for key, value in catalog.items():
if "data_sheets" in value:
if value["data_sheets"] is not None:
paths.append(value["data_sheets"]["data_sheet"])
for path in paths:
media_url = "http://some_url.com:8000" + path
print(media_url)
# Parsing the url and extracting only the datasheet name
parsed_url = parse.urlsplit(media_url).path
datasheet_name = parsed_url.split("/")[-1]
response = requests.get(media_url)
datasheet_path = os.path.join(self._output_path, datasheet_name)
with open(datasheet_path, 'wb') as file:
file.write(response.content)
I am trying to get the datasheet to be in a subfolder called datasheets, but the current implementation only allows me to get the datasheets in the ._output_path, which is the folder that I select.
What I really want is to be able to have something like: output_path_folder/datasheets_folder/datasheet_name.
UPDATE: so basically this is a method that extracts datasheets from a website and saves them locally, some sort of download. I gets stored with some other files so I want to have a subdirectory inside of the main directory that would allow me to store the datasheets. Hope it makes sense now
Any help would be greatly appreciated
I would suggest the standard python library pathlib for working with paths.
from pathlib import Path
datasheet_path = Path(self._output_path) / "datasheets" / datasheet_name
datasheet_path.parent.mkdir(parents=True, exist_ok=True)
To fit your edit it would look something like this:
from pathlib import Path
def get_datasheets(self, build_id):
catalog = self._get_catalogue(build_id)
paths = []
for key, value in catalog.items():
if "data_sheets" in value:
if value["data_sheets"] is not None:
paths.append(value["data_sheets"]["data_sheet"])
for path in paths:
media_url = "http://some_url.com:8000" + path
print(media_url)
# Parsing the url and extracting only the datasheet name
parsed_url = parse.urlsplit(media_url).path
datasheet_name = parsed_url.split("/")[-1]
response = requests.get(media_url)
datasheet_path = Path(self._output_path) / "datasheets" / datasheet_name
# takes the parent from the hole path and creates all directorys that are missing
datasheet_path.parent.mkdir(parents=True, exist_ok=True)
with open(datasheet_path, 'wb') as file:
file.write(response.content)
I have one tex file and three images and I want that the user can click a button and download all three of them. It would be ideal if the four files would be as one tar file. My download works as follows right now
#app.route('/download_tex', methods=['GET', 'POST'])
#login_required
def download_tex():
latext_text = render_template('get_lates.html')
filename = 'test'
response = make_response(latext_text)
response.headers["Content-Disposition"] = "attachment; filename=%s.tex" % filename
return response
this works fine for the tex file, but how can I tar up files within the flask app and send the tar file instead?
EDIT: Ok thanks to the comment below I came up with this code
latext_text = render_template('get_latex.html')
latex_file = open(basedir + '/app/static/statistics/latex_%s.tex' % current_user.username, "w")
latex_file.write(latext_text)
latex_file.close()
filename = 'tarfile_%s.tar.gz' % current_user.username
filepath = basedir + '/app/static/statistics/%s' % filename
tar = tarfile.open(filepath, "w:gz")
tar.add(basedir + '/app/static/statistics/image1.png')
tar.add(basedir + '/app/static/statistics/image2.png')
tar.add(basedir + '/app/static/statistics/image3.png')
tar.add(basedir + '/app/static/statistics/latex_%s.tex' % current_user.username)
tar.close()
but how can I now download that tar file with the browser?
You should use the send_from_directory method that Flask provides for this =) It is the perfect use case for what you're doing.
What you can do is something like this:
from flask import send_from_directory
# code here ...
filename = 'tarfile_%s.tar.gz' % current_user.username
filedir = basedir + '/app/static/statistics/'
# tar code here ...
return send_from_directory(filedir, filename, as_attachment=True)
That will handle all of the downloading bits for you in a clean way.
I have PDF files which are stored on the server. I am writing a code which prompts users to download the PDF file. I used the following code:
filename ="somepdf.pdf"
filedir = "media/"
filepath = os.path.join( filedir, filename )
pdf=open(filepath)
response = HttpResponse(pdf.read(),content_type='application/pdf')
response['Content-Disposition'] = 'attachment;filename=%s' % filename
return response
For some reason, I rechecked the PDF file that was prompted. The PDF file are not readable (corrupted file perhaps).
Do you know what happen?
You have missed MEDIA_ROOT:
from settings import MEDIA_ROOT
...
filepath = os.path.join(MEDIA_ROOT, filedir, filename)
I found what the answer is.
Apparently the Media_ROOT and Media_URL doesn't work in my case. I use the web browsing debugging tool and locate the discrepancy between the link and the actual PDF.
It should be "/media/" not "media"
I used this code in the HTML to serve the file:
<embed height="100%" width="100%" name="plugin" src="/media/receipts/Receipt_1.pdf" type="application/pdf">
Is it possible to use flask to browse through a directory with files?
My code never seems to work correctly as weird appending between strings happens.
Also I don`t know how to implement a kind of check whether the path is a file or a folder.
Here is my Flask app.route:
#app.route('/files', defaults={'folder': None,'sub_folder': None}, methods=['GET'])
#app.route('/files/<folder>', defaults={'sub_folder': None}, methods=['GET'])
#app.route('/files/<folder>/<sub_folder>', methods=['GET'])
def files(folder,sub_folder):
basedir = 'files/'
directory = ''
if folder != None:
directory = directory + '/' + folder
if sub_folder != None:
directory = directory + '/' + sub_folder
files = os.listdir(basedir + directory)
return render_template('files.html',files=files,directory=basedir + directory,currdir=directory)
and here is my html template, if anyone could give me some pointers it would be greatly appreciated!
<body>
<h2>Files {{ currdir }}</h2> </br>
{% for name in files: %}
{{ name }} </br></br>
{% endfor %}
</body>s.html',files=files,directory=basedir + directory,currdir=directory)
A path converter (docs link) in the url structure is better than hardcoding all the different possible path structures.
os.path.exists can be used to check if the path is valid and os.path.isfile and os.path.isdir for checking if the path is a file or a directory, respectively.
Endpoint:
#app.route('/', defaults={'req_path': ''})
#app.route('/<path:req_path>')
def dir_listing(req_path):
BASE_DIR = '/Users/vivek/Desktop'
# Joining the base and the requested path
abs_path = os.path.join(BASE_DIR, req_path)
# Return 404 if path doesn't exist
if not os.path.exists(abs_path):
return abort(404)
# Check if path is a file and serve
if os.path.isfile(abs_path):
return send_file(abs_path)
# Show directory contents
files = os.listdir(abs_path)
return render_template('files.html', files=files)
Template (Now with directory browsing :) ):
<ul>
{% for file in files %}
<li>
<a href="{{ (request.path + '/' if request.path != '/' else '') + file }}">
{{ (request.path + '/' if request.path != '/' else '') + file }}
</a>
</li>
{% endfor %}
</ul>
Note: abort and send_file functions were imported from flask.
Here is a working example.
# app.py
from flask import Flask
from flask_autoindex import AutoIndex
app = Flask(__name__)
ppath = "/" # update your own parent directory here
app = Flask(__name__)
AutoIndex(app, browse_root=ppath)
if __name__ == "__main__":
app.run()
Here is a working repo
https://github.com/MrAmbiG/folderview
I created this function for my project ... it is working perfectly ... it start browsing at this folder /home/myuser/myfolder
#app.route('/myfolder/<path:folders>')
#app.route('/myfolder/')
def mybrowser(folders=''):
environ = flask.request.environ
path = environ.get('PATH_INFO')
path = path.lower()
#if path=='/myfolder': return flask.redirect(path+'/',code=307)
os_path = '/home/myuser'+path.rstrip('/')
if path.endswith('/'):
HTML_HEADER = """<html><head><title>Index of {path_title}</title></head><body bgcolor="white"><h1>Index of {path_title}</h1><hr><pre>../\n"""
HTML_FOOTER = "</pre><hr></body></html>"
path_title = os_path.split('myuser')[1]+'/'
html = HTML_HEADER.format(path_title=path_title)
import os,time
files = os.listdir(os_path)
for file in files:
path = os_path+'/'+file
size = str(os.path.getsize(path))
date = os.path.getmtime(path)
date = time.gmtime(date)
date = time.strftime('%d-%b-%Y %H:%M',date)
spaces1 = ' '*(50-len(file))
spaces2 = ' '*(20-len(size))
if os.path.isdir(path): html += '' + file + '/'+spaces1+date+spaces2+' -\n'
else: html += '' + file + ''+spaces1+' '+date+spaces2+size+'\n'
html += HTML_FOOTER
#open(os_path+'/index.html','w').write(html)
response_headers = {'Content-Type':'text/html','Content-Length':str(len(html))}
status = '200 OK'
response = flask.Response(html,status=status,headers=response_headers)
else:
response = flask.send_file(os_path,conditional=True)
return response
Here's a quick and dirty implementation using pathlib's .iterdir and Flask.send_from_directory to create dynamic routes to files in the same directory as this flask app and generates a unordered list of links to be displayed at the root route.
This isn't recursive. It won't create routes for sub-directories or files within subdirectories. It's what I needed when I came looking here on SO for answers.
"""Simple Flask App to serve the contents of the current directory.
$ python serve_directory.py
this serves browseable contents of this file's directory.
to http://localhost:8080.
"""
from __future__ import annotations
from pathlib import Path
from typing import TYPE_CHECKING
from flask import Flask, send_from_directory
if TYPE_CHECKING:
from typing import Iterator
from flask import Response
# Instantiate a Flask app object
app: Flask = Flask(__name__)
# Get the parent directory of this script. (Global)
DIR_PATH: Path = Path(__file__).parent
def get_files_from_this_directory() -> Iterator[str]:
"""Generate the items within this script's directory.
Yields:
Generator: item(s) in __file__'s directory.
"""
for dir_item in DIR_PATH.iterdir():
yield dir_item.name
#app.route("/files/<file_name>") # type: ignore
def serve_file(file_name: str) -> Response:
"""Set up a dynamic routes for directory items at /files/.
Args:
file_name (str): regular file.
Returns:
Response: regular file.
"""
return send_from_directory(DIR_PATH, file_name)
def html_ul_of_items() -> str:
"""Create a unordered list of anchors/links to file routes.
Returns:
str: a <ul> with N <li> elements where N is the number of
elements in __file__'s directory.
"""
html: str = "<ul>"
for dir_item in get_files_from_this_directory():
html += f"<li><a href='files/{dir_item}'>{dir_item}</a`></li>"
return f"{html}</ul>"
#app.route("/") # type: ignore
def serve_index() -> str:
"""Root route which displays an unordered list of directory items.
Returns:
str: a <ul> with N <li> elements where N is the number of
elements in __file__'s directory.
"""
return html_ul_of_items()
def main() -> None:
"""Run the flask app."""
app.run(port=8080)
if __name__ == "__main__":
main()
In my view callable, I want users to be able to create a new file called filename like so:
#view_config(route_name='home_page', renderer='templates/edit.pt')
def home_page(request):
if 'form.submitted' in request.params:
name= request.params['name']
input_file=request.POST['stl'].filename
vertices, normals = [],[]
for line in input_file:
parts = line.split()
if parts[0] == 'vertex':
vertices.append(map(float, parts[1:4]))
elif parts[0] == 'facet':
normals.append(map(float, parts[2:5]))
ordering=[]
N=len(normals)
...parsing data...
data=[vertices,ordering]
jsdata=json.dumps(data)
renderer_dict = dict(name=name,data=jsdata)
app_dir = request.registry.settings['upload_dir']
filename = "%s/%s" % ( app_dir , name )
html_string = render('tutorial:templates/view.pt', renderer_dict, request=request)
with open(filename,'w') as file:
file.write(new_comment)
return HTTPFound(location=request.static_url('tutorial:pages/%(pagename)s.html' % {'pagename': name}))
return {}
right now, when I attempt to upload a file, I am getting this error message: IOError: [Errno 2] No such file or directory: u'/path/pages/one' (one is the name variable) I believe this is because I am incorrectly defining the app_dir variable. I want filename to be the url of the new file that is being created with the name variable that is defined above (so that it can be accessed at www.domain.com/pages/name). Here is the file structure of my app:
env
tutorial
tutorial
templates
home.pt
static
pages
(name1)
(name2)
(name3)
....
views.py
__init__.py
In my init.py I have:
config.add_static_view(name='path/pages/', path=config.registry.settings['upload_dir'])
In my development.ini file I have
[app:main]
use = egg:tutorial
upload_dir = /path/pages
Edit: If anyone has an idea on why this question isn't getting much attention, I would love to hear it.
While I feel like you probably have a misunderstanding of how to serve up user-generated content, I will show you a way to do what you're asking. Generally user-generated content would not be uploaded into your source, you'll provide some configurable spot outside to place it, as I show below.
Make the path configurable via your INI file:
[app:main]
use = egg:tutorial
upload_dir = /path/to/writable/upload/directory
Add a static view that can serve up files under that directory.
config.add_static_view(name='/url/to/user_uploads', path=config.registry.settings['upload_dir'])
In your upload view you can get your app_dir via
app_dir = request.registry.settings['upload_dir']
Copy the data there, and from then on it'll be available at /url/to/user_uploads/filename.