I CAN'T figure out why my uploaded file to Dropbox via Django is always zero bytes.
Outsize Django (using raw Python), the files get uploaded normally.
My HTML has enctype="multipart/form-data" declared.
VIEWS.PY:
if cv_form.is_valid():
cv_form.save(commit=True)
# print(request.FILES['cv'].size) == 125898
DOC = request.FILES['cv']
PATH = f'/CV/{DOC}'
upload_handler(DOC, PATH)
#http_response_happens_here()
HANDLER:
def upload_handler(DOC, PATH):
dbx = dropbox.Dropbox(settings.DROPBOX_APP_ACCESS_TOKEN)
dbx.files_upload(DOC.file.read(), PATH)
#file gets uploaded but always 0bytes in size
My bad! How did I not see it.
The solution incase anyone else runs into the same issue. Battled it for a while myself.
if cv_form.is_valid():
cv_form.save(commit=False) # commit should be False before upload
# print(request.FILES['cv'].size) == 125898
DOC = request.FILES['cv']
PATH = f'/CV/{DOC}'
upload_handler(DOC, PATH)
cv_form.save(commit=True) # now you can save the file.
#http_response_happens_here()
Related
I am new in python and django, right now I would like to upload an image from postman (content type: form-data) and then save it in server. So far I have doing this
#csrf_exempt
def detector(request):
data = {"success": False}
if request.method == "POST":
print("oke0")
# check to see if an image was uploaded
if request.FILES.get("image", None) is not None:
...# here I would like to save the image
else:
return JsonResponse(data)
return JsonResponse(data)
so the flow is: upload image from postman and then directory 'media' will be created and the image will be stored there
so far I have been following this https://www.geeksforgeeks.org/python-uploading-images-in-django/ but I don't know how to try it in postman, anyone knows step by step to save image file to server in django?
Here is the code, but keep in mind that I didn't test it, since I wrote it on the fly.
I also assume you use Python3.2+, since you won't be able to use os.makedirs with exist_ok flag.
If you're using Python3.5+, you can also replace that code with something like Pathlib which can create folder, but won't raise an exception like so:
import pathlib
pathlib.Path('save_path').mkdir(parents=True, exist_ok=True)
and you can replace the os.makedirs in the code bellow with this call in that case.
import os
import uuid
#csrf_exempt
def detector(request):
data = {"success": False}
if request.method == "POST":
print("oke0")
if request.FILES.get("image", None) is not None:
#So this would be the logic
img = request.FILES["image"]
img_extension = os.path.splitext(img.name)[1]
# This will generate random folder for saving your image using UUID
save_path = "static/" + str(uuid.uuid4())
if not os.path.exists(save_path):
# This will ensure that the path is created properly and will raise exception if the directory already exists
os.makedirs(os.path.dirname(save_path), exist_ok=True)
# Create image save path with title
img_save_path = "%s/%s%s" % (save_path, "image", img_extension)
with open(img_save_path, "wb+") as f:
for chunk in img.chunks():
f.write(chunk)
data = {"success": True}
else:
return JsonResponse(data)
return JsonResponse(data)
Now, that's an easy part.
For Postman, simply follow this answer -> https://stackoverflow.com/a/49210637/1737811
Hope this answers your question.
I created a document site on plone from which file uploads can be made. I saw that plone saves them in the filesystem in the form of a blob, now I need to take them through a python script that will process the pdfs downloaded with an OCR. Does anyone have any idea how to do it? Thank you
Not sure how to extract PDFs from BLOB-storage or if it's possible at all, but you can extract them from a running Plone-site (e.g. executing the script via a browser-view):
import os
from Products.CMFCore.utils import getToolByName
def isPdf(search_result):
"""Check mime_type for Plone >= 5.1, otherwise check file-extension."""
if mimeTypeIsPdf(search_result) or search_result.id.endswith('.pdf'):
return True
return False
def mimeTypeIsPdf(search_result):
"""
Plone-5.1 introduced the mime_type-attribute on files.
Try to get it, if it doesn't exist, fail silently.
Return True if mime_type exists and is PDF, otherwise False.
"""
try:
mime_type = search_result.mime_type
if mime_type == 'application/pdf':
return True
except:
pass
return False
def exportPdfFiles(context, export_path):
"""
Get all PDF-files of site and write them to export_path on the filessytem.
Remain folder-structure of site.
"""
catalog = getToolByName(context, 'portal_catalog')
search_results = catalog(portal_type='File', Language='all')
for search_result in search_results:
# For each PDF-file:
if isPdf(search_result):
file_path = export_path + search_result.getPath()
file_content = search_result.getObject().data
parent_path = '/'.join(file_path.split('/')[:-1])
# Create missing directories on the fly:
if not os.path.exists(parent_path):
os.makedirs(parent_path)
# Write PDF:
with open(file_path, 'w') as fil:
fil.write(file_content)
print 'Wrote ' + file_path
print 'Finished exporting PDF-files to ' + export_path
The example keeps the folder-structure of the Plone-site in the export-directory. If you want them flat in one directory, a handler for duplicate file-names is needed.
my users can upload an image of themselves and use that as an avatar. Now I am struggling how to retrieve a default fallback image if they haven't uploaded an image themselves.
The path to the avatar is "//mysite.com/avatar/username".
So far I have this code, which works fine when the user has uploaded an avatar themselves, but it gives me the following error when I try to retrieve the default image:
raise IOError(errno.EACCES, 'file not accessible', filename)
IOError: [Errno 13] file not accessible: '/Users/myuser/Documents/github/mysite/static/images/profile.png'
def get(self):
path = self.request.path.split('/')
action = self.get_action(path)
if action:
e = employees.filter('username = ', action).get()
if e.avatar:
self.response.headers['Content-Type'] = "image/png"
self.response.out.write(e.avatar)
else:
self.response.headers['Content-Type'] = 'image/png'
path = os.path.join(os.path.split(__file__)[0], 'static/images/profile.png')
with open(path, 'r') as f:
print self.response.out.write(f.read())
I have defined the "/static"-folder as a static_dir in my app.yaml.
I know I can place the profile.png in the root-folder, but I prefer to have it in the "/static/images"-folder.
Any ideas?
If you declared the file itself as a static_file or its directory or any directory in its filepath a static_dir inside your app/service's .yaml config file then, by default, it's not accessible to the application code.
You need to also configure it as application_readable. From Handlers element:
application_readable
Optional. Boolean. By default, files declared in static file handlers
are uploaded as static data and are only served to end users. They
cannot be read by an application. If this field is set to true, the
files are also uploaded as code data so your application can read
them. Both uploads are charged against your code and static data
storage resource quotas.
I am trying to add some validation for user uploaded files. This requires running through a custom script I made called "sumpin", which only takes a filepath as a variable and sends back JSON data that will verify. Everything inside my script is working independently, putting it together where the error occurs.
Since this is file validation, I decided to expand my file_extension validator that was already working.
models.py
from allauthdemo.fileuploadapp.slic3rcheck import sumpin
def user_directory_path_files(instance, filename):
return os.path.join('uploads', str(instance.objectid), filename)
def validate_file_extension(value):
ext = os.path.splitext(value.name)[1]
valid_extensions = ['.stl','.STL']
if not ext in valid_extensions:
raise ValidationError(u'Please upload a .stl file type only')
data = sumpin(value.path)
print (data)
class subfiles(models.Model):
STL = models.FileField(_('STL Upload'),
upload_to=user_directory_path_files, validators=[validate_file_extension])
The error that I get is that the path (value.path) is not valid.
This is the incorrect path because the upload_to tag must change this at a later point. This may be obvious, but I also need to have the file at the filepath location when my script is called. So essentially my questions are...
How can pass the "upload_to" path into my validator to run through my custom script?
Is there a better method to deal with uploaded files, like in the main class with a "save" or "clean" function?
I've found my own answer, but I'll post it here in case someone runs across this issue in the future.
I was incorrect, a validator wouldn't actually download the file. I need to use a file upload handler, which is shown below.
import os
from django.core.files.storage import default_storage
from allauthdemo.fileuploadapp.slic3rcheck import sumpin
def handle_uploaded_file(f):
with open(default_storage.path('tmp/'+f.name), 'wb+') as destination:
for chunk in f.chunks():
destination.write(chunk)
data = sumpin(default_storage.path('tmp/'+f.name))
os.remove(default_storage.path('tmp/'+f.name))
return data
then I call this inside my views.py.
from allauthdemo.fileuploadapp.uploadhandler import handle_uploaded_file
#login_required
def STLupload(request):
# Handle file upload
if request.method == 'POST':
formA = ObjectUp(request.POST, request.FILES)
if formA is_valid():
data = handle_uploaded_file(request.FILES['STL'])
This will return whatever I called to return within handle_upload_file, which worked perfect for my issues. Hopefully someone will find this useful the future.
I am trying to let a user upload an image, save the image to disk, and then have it display on a webpage, but I can't get the image to display properly. Here is my bin/app.py:
import web
urls = (
'/hello', 'index'
)
app = web.application(urls, globals())
render = web.template.render('templates/', base="layout")
class index:
def GET(self):
return render.hello_form()
def POST(self):
form = web.input(greet="Hello", name="Nobody", datafile={})
greeting = "%s, %s" % (form.greet, form.name)
filedir = 'absolute/path/to/directory'
filename = None
if form.datafile:
# replaces the windows-style slashes with linux ones.
filepath = form.datafile.filename.replace('\\','/')
# splits the and chooses the last part (the filename with extension)
filename = filepath.split('/')[-1]
# creates the file where the uploaded file should be stored
fout = open(filedir +'/'+ filename,'w')
# writes the uploaded file to the newly created file.
fout.write(form.datafile.file.read())
# closes the file, upload complete.
fout.close()
filename = filedir + "/" + filename
return render.index(greeting, filename)
if __name__ == "__main__":
app.run()
and here is templates/index.html:
$def with (greeting, datafile)
$if greeting:
I just wanted to say <em style="color: green; font-size: 2em;">$greeting</em>
$else:
<em>Hello</em>, world!
<br>
$if datafile:
<img src=$datafile alt="your picture">
<br>
Go Back
When I do this, I get a broken link for the image. How do I get the image to display properly? Ideally, I wouldn't have to read from disk to display it, although I'm not sure if that's possible. Also, is there a way to write the file to the relative path, instead of the absolute path?
You can also insert a path to all images in a folder by adding an entry to your URL.
URL = ('/hello','Index',
'/hello/image/(.*)','ImageDisplay'
)
...
class ImageDisplay(object):
def GET(self,fileName):
imageBinary = open("/relative/path/from/YourApp}"+fileName,'rb').read()
return imageBinary
Not the ../YourApp, not ./YourApp. It looks up one directory from where your prgram is. Now, in the html, you can use
<img src="/image/"+$datafile alt="your picture">
I would recommend using with or try with the "imageBinary = open("{..." line.
Let me know if more info is needed. This is my first response.
Sorry to ask a question in a responce, but is there a way to use a regular expression, like (.jpg) in place of the (.) I have in the URL definition?
web.py doesn't automatically serve all of the files from the directory your application is running in — if it did, anyone could be able to read your application's source code. It does, however, have a directory it serves files out of: static.
To answer your other question: yes, there is a way to avoid using an absolute path: give it a relative path!
Here's how your code might look afterwards:
filename = form.datafile.filename.replace('\\', '/').split('/')[-1]
# It might be a good idea to sanitize filename further.
# A with statement ensures that the file will be closed even if an exception is
# thrown.
with open(os.path.join('static', filename), 'wb') as f:
# shutil.copyfileobj copies the file in chunks, so it will still work if the
# file is too large to fit into memory
shutil.copyfileobj(form.datafile.file, f)
Do omit the filename = filedir + "/" + filename line. Your template need not include the absolute path: in fact, it should not; you must include static/; no more, no less:
<img src="static/$datafile" alt="your picture">