def test_retrieve_view(self): self._submit_transport_instance_w_attachment() pk = self.attachment.pk data = { 'url': 'http://testserver/api/v1/media/%s' % pk, 'field_xpath': None, 'download_url': self.attachment.media_file.url, 'small_download_url': image_url(self.attachment, 'small'), 'medium_download_url': image_url(self.attachment, 'medium'), 'id': pk, 'xform': self.xform.pk, 'instance': self.attachment.instance.pk, 'mimetype': self.attachment.mimetype, 'filename': self.attachment.media_file.name } request = self.factory.get('/', **self.extra) response = self.retrieve_view(request, pk=pk) self.assertNotEqual(response.get('Last-Modified'), None) self.assertEqual(response.status_code, 200) self.assertTrue(isinstance(response.data, dict)) self.assertEqual(response.data, data) # file download filename = data['filename'] ext = filename[filename.rindex('.') + 1:] request = self.factory.get('/', **self.extra) response = self.retrieve_view(request, pk=pk, format=ext) self.assertNotEqual(response.get('Last-Modified'), None) self.assertEqual(response.status_code, 200) self.assertEqual(response.content_type, 'image/jpeg')
def get_attachment_data(attachment, suffix): if suffix in list(settings.THUMB_CONF): image_url(attachment, suffix) suffix = settings.THUMB_CONF.get(suffix).get('suffix') f = default_storage.open(get_path(attachment.media_file.name, suffix)) data = f.read() else: data = attachment.media_file.read() return data
def get_attachment_data(attachment, suffix): if suffix in settings.THUMB_CONF.keys(): image_url(attachment, suffix) suffix = settings.THUMB_CONF.get(suffix).get('suffix') f = default_storage.open( get_path(attachment.media_file.name, suffix)) data = f.read() else: data = attachment.media_file.read() return data
def attachment_url(request, size='medium'): media_file = request.GET.get('media_file') # TODO: how to make sure we have the right media file, # this assumes duplicates are the same file result = Attachment.objects.filter(media_file=media_file)[0:1] if result.count() == 0: pattern = re.compile('(.*)-(\d+)_(\d+)_(\d+)\.(.*)') m = pattern.search(media_file) if m: pattern = re.compile('(.*)-(.*)\.(.*)') m = pattern.search(media_file) media_file = media_file.replace("-"+m.group(2), "") result = Attachment.objects.filter(media_file=media_file)[0:1] else: return HttpResponseNotFound(_(u'Attachment not found')) attachment = result[0] if not attachment.mimetype.startswith('image'): return redirect(attachment.media_file.url) try: media_url = image_url(attachment, size) except: # TODO: log this somewhere # image not found, 404, S3ResponseError timeouts pass else: if media_url: return redirect(media_url) return HttpResponseNotFound(_(u'Error: Attachment not found'))
def attachment_url(request, size='medium'): """ Redirects to image attachment of the specified size, defaults to 'medium'. """ media_file = request.GET.get('media_file') no_redirect = request.GET.get('no_redirect') if not media_file: return HttpResponseNotFound(_(u'Attachment not found')) result = Attachment.objects.filter(media_file=media_file).order_by()[0:1] if not result: return HttpResponseNotFound(_(u'Attachment not found')) attachment = result[0] if size == 'original' and no_redirect == 'true': response = response_with_mimetype_and_name( attachment.mimetype, attachment.name, extension=attachment.extension, file_path=attachment.media_file.name) return response if not attachment.mimetype.startswith('image'): return redirect(attachment.media_file.url) media_url = image_url(attachment, size) if media_url: return redirect(media_url) return HttpResponseNotFound(_(u'Error: Attachment not found'))
def attachment_url(request, size='medium'): """ Redirects to image attachment of the specified size, defaults to 'medium'. """ media_file = request.GET.get('media_file') no_redirect = request.GET.get('no_redirect') if not media_file: return HttpResponseNotFound(_(u'Attachment not found')) result = Attachment.objects.filter(media_file=media_file)[0:1] if result.count() == 0: return HttpResponseNotFound(_(u'Attachment not found')) attachment = result[0] if size == 'original' and no_redirect == 'true': response = response_with_mimetype_and_name( attachment.mimetype, attachment.name, extension=attachment.extension, file_path=attachment.media_file.name) return response if not attachment.mimetype.startswith('image'): return redirect(attachment.media_file.url) media_url = image_url(attachment, size) if media_url: return redirect(media_url) return HttpResponseNotFound(_(u'Error: Attachment not found'))
def attachment_url(request, size='medium'): media_file = request.GET.get('media_file') no_redirect = request.GET.get('no_redirect') # TODO: how to make sure we have the right media file, # this assumes duplicates are the same file result = Attachment.objects.filter(media_file=media_file)[0:1] if result.count() == 0: return HttpResponseNotFound(_(u'Attachment not found')) attachment = result[0] if size == 'original' and no_redirect == 'true': response = response_with_mimetype_and_name( attachment.mimetype, attachment.name, extension=attachment.extension, file_path=attachment.media_file.name) return response if not attachment.mimetype.startswith('image'): return redirect(attachment.media_file.url) try: media_url = image_url(attachment, size) except: # TODO: log this somewhere # image not found, 404, S3ResponseError timeouts pass else: if media_url: return redirect(media_url) return HttpResponseNotFound(_(u'Error: Attachment not found'))
def attachment_url(request, size='medium'): media_file = request.GET.get('media_file') # TODO: how to make sure we have the right media file, # this assumes duplicates are the same file if media_file: mtch = re.search('^([^\/]+)/attachments(/[^\/]+)$', media_file) if mtch: # in cases where the media_file url created by instance.html's # _attachment_url function is in the wrong format, this will # match attachments with the correct owner and the same file name (username, filename) = mtch.groups() result = Attachment.objects.filter(**{ 'instance__xform__user__username': username, }).filter(**{ 'media_file__endswith': filename, })[0:1] else: # search for media_file with exact matching name result = Attachment.objects.filter(media_file=media_file)[0:1] if result.count() == 0: media_file_logger.info('attachment not found') return HttpResponseNotFound(_(u'Attachment not found')) attachment = result[0] if not attachment.mimetype.startswith('image'): return redirect(attachment.media_file.url) try: media_url = image_url(attachment, size) except: media_file_logger.error('could not get thumbnail for image', exc_info=True) else: if media_url: return redirect(media_url) return HttpResponseNotFound(_(u'Error: Attachment not found'))
def append_row(self, question_name, question_label, question_type, answer_dict): styNormal = self.bodystyle styBackground = ParagraphStyle('background', parent=styNormal, backColor=colors.white) if question_name in answer_dict: if question_type == 'note': answer = Paragraph('', styBackground) isNull = True elif question_type == 'photo': #photo = '/media/user/attachments/'+ r_answer[r_question+"/"+question] size = "small" try: result = Attachment.objects.filter( media_file=self.media_folder + '/attachments/' + answer_dict[question_name])[0:1] attachment = result[0] if not attachment.mimetype.startswith('image'): media_url = 'http://' + self.base_url + '/static/images/img-404.jpg' media_url = image_url(attachment, size) except: media_url = 'http://' + self.base_url + '/static/images/img-404.jpg' answer = self.create_logo(media_url) isNull = False # answer ='' elif question_type == 'audio' or question_type == 'video': media_link = 'http://' + self.base_url + '/attachment/medium?media_file=' + self.media_folder + '/attachments/' + answer_dict[ question_name] answer = Paragraph( '<link href="' + media_link + '">Attachment</link>', styBackground) isNull = False else: answer_text = answer_dict[question_name] if len(answer_text) > 1200: new_answer_text = answer_text[0:360] answer_text = new_answer_text + ".... ( full answer followed after this table. )" self.additional_data.append( {question_label: answer_dict[question_name]}) answer = Paragraph(answer_text, styBackground) isNull = False else: answer = Paragraph('', styBackground) isNull = True if self.removeNullField and isNull: pass else: row = [Paragraph(question_label, styBackground), answer] self.data.append(row)
def test_thumbnails(self): for attachment in Attachment.objects.filter(instance=self.instance): url = image_url(attachment, 'small') filename = attachment.media_file.name.replace('.jpg', '') thumbnail = '%s-small.jpg' % filename self.assertNotEqual(url.find(thumbnail), -1) for size in ['small', 'medium', 'large']: thumbnail = f'{filename}-{size}.jpg' self.assertTrue(default_storage.exists(thumbnail)) default_storage.delete(thumbnail)
def test_thumbnails(self): for attachment in Attachment.objects.filter(instance=self.instance): url = image_url(attachment, 'small') filename = attachment.media_file.name.replace('.jpg', '') thumbnail = '%s-small.jpg' % filename self.assertNotEqual( url.find(thumbnail), -1) for size in ['small', 'medium', 'large']: thumbnail = '%s-%s.jpg' % (filename, size) self.assertTrue( default_storage.exists(thumbnail)) default_storage.delete(thumbnail)
def retrieve(self, request, pk=None): """ Redirect to final attachment url param pk: the attachment id query param filename: the filename of the associated attachment is required and has to match query param suffix: (optional) - specify small | medium | large to return resized images. return HttpResponseRedirect: redirects to final image url """ try: int(pk) except ValueError: raise Http404() else: filename = request.query_params.get('filename') attachments = Attachment.objects.all() obj = get_object_or_404(attachments, pk=pk) if obj.media_file.name != filename: raise Http404() url = None if obj.mimetype.startswith('image'): suffix = request.query_params.get('suffix') if suffix: if suffix in list(settings.THUMB_CONF): try: url = image_url(obj, suffix) except Exception as e: raise ParseError(e) else: raise Http404() if not url: response = generate_media_download_url(obj) return response return HttpResponseRedirect(url) raise Http404()
def attachment_url(request, size='medium'): media_file = request.GET.get('media_file') # TODO: how to make sure we have the right media file, # this assumes duplicates are the same file result = Attachment.objects.filter(media_file=media_file)[0:1] if result.count() == 0: return HttpResponseNotFound(_(u'Attachment not found')) attachment = result[0] if not attachment.mimetype.startswith('image'): return redirect(attachment.media_file.url) try: media_url = image_url(attachment, size) except: # TODO: log this somewhere # image not found, 404, S3ResponseError timeouts pass else: if media_url: return redirect(media_url) return HttpResponseNotFound(_(u'Error: Attachment not found'))
def retrieve(self, request, pk=None): """ Redirect to final attachment url param pk: the attachment id query param filename: the filename of the associated attachment is required and has to match query param suffix: (optional) - specify small | medium | large to retuurn resized images. return HttpResponseRedirect: redirects to final image url """ try: int(pk) except ValueError: raise Http404() else: filename = request.QUERY_PARAMS.get('filename') attachments = Attachment.objects.all() obj = get_object_or_404(attachments, pk=pk) if obj.media_file.name != filename: raise Http404() url = None if obj.mimetype.startswith('image'): suffix = request.QUERY_PARAMS.get('suffix') if suffix: if suffix in settings.THUMB_CONF.keys(): url = image_url(obj, suffix) else: raise Http404() if not url: url = obj.media_file.url return HttpResponseRedirect(url) raise Http404()
def attachment_url(request, size='medium'): media_file = request.GET.get('media_file') # TODO: how to make sure we have the right media file, # this assumes duplicates are the same file if media_file: mtch = re.search('^([^\/]+)/attachments(/[^\/]+)$', media_file) if mtch: # in cases where the media_file url created by instance.html's # _attachment_url function is in the wrong format, this will # match attachments with the correct owner and the same file name (username, filename) = mtch.groups() result = Attachment.objects.filter( **{ 'instance__xform__user__username': username, }).filter(**{ 'media_file__endswith': filename, })[0:1] else: # search for media_file with exact matching name result = Attachment.objects.filter(media_file=media_file)[0:1] if len(result) == 0: media_file_logger.info('attachment not found') return HttpResponseNotFound(_(u'Attachment not found')) attachment = result[0] if not attachment.mimetype.startswith('image'): return redirect(attachment.media_file.url) try: media_url = image_url(attachment, size) except: media_file_logger.error('could not get thumbnail for image', exc_info=True) else: if media_url: return redirect(media_url) return HttpResponseNotFound(_(u'Error: Attachment not found'))
def attachment_url(request, size='medium'): media_file = request.GET.get('media_file') # TODO: how to make sure we have the right media file, # this assumes duplicates are the same file. # # Django seems to already handle that. It appends datetime to the filename. # It means duplicated would be only for the same user who uploaded two files # with same name at the same second. if media_file: mtch = re.search(r'^([^/]+)/attachments/([^/]+)$', media_file) if mtch: # in cases where the media_file url created by instance.html's # _attachment_url function is in the wrong format, this will # match attachments with the correct owner and the same file name (username, filename) = mtch.groups() result = Attachment.objects.filter( instance__xform__user__username=username, ).filter( Q(media_file_basename=filename) | Q(media_file_basename=None, media_file__endswith='/' + filename))[0:1] else: # search for media_file with exact matching name result = Attachment.objects.filter(media_file=media_file)[0:1] try: attachment = result[0] return redirect(attachment.media_file.url) except IndexError: media_file_logger.info('attachment not found') return HttpResponseNotFound(_(u'Attachment not found')) # Checks whether users are allowed to see the media file before giving them # the url xform = attachment.instance.xform if not request.user.is_authenticated(): # This is not a DRF view, but we need to honor things like # `DigestAuthentication` (ODK Briefcase uses it!) and # `TokenAuthentication`. Let's try all the DRF authentication # classes before giving up drf_request = rest_framework.request.Request(request) for auth_class in api_settings.DEFAULT_AUTHENTICATION_CLASSES: auth_tuple = auth_class().authenticate(drf_request) if auth_tuple is not None: # Is it kosher to modify `request`? Let's do it anyway # since that's what `has_permission()` requires... request.user = auth_tuple[0] # `DEFAULT_AUTHENTICATION_CLASSES` are ordered and the # first match wins; don't look any further break if not has_permission(xform, xform.user, request): return HttpResponseForbidden(_(u'Not shared.')) media_url = None if not attachment.mimetype.startswith('image'): media_url = attachment.media_file.url else: try: media_url = image_url(attachment, size) except: media_file_logger.error('could not get thumbnail for image', exc_info=True) if media_url: # We want nginx to serve the media (instead of redirecting the media itself) # PROS: # - It avoids revealing the real location of the media. # - Full control on permission # CONS: # - When using S3 Storage, traffic is multiplied by 2. # S3 -> Nginx -> User response = HttpResponse() default_storage = get_storage_class()() if not isinstance(default_storage, FileSystemStorage): # Double-encode the S3 URL to take advantage of NGINX's # otherwise troublesome automatic decoding # protected_url = '/protected-s3/{}'.format(urlquote(media_url)) return redirect(media_url) else: return redirect(media_url) # protected_url = media_url.replace(settings.MEDIA_URL, "/protected/") # Let nginx determine the correct content type response["Content-Type"] = "" response["X-Accel-Redirect"] = protected_url return response return HttpResponseNotFound(_(u'Error: Attachment not found'))
def attachment_url(request, size='medium'): media_file = request.GET.get('media_file') # TODO: how to make sure we have the right media file, # this assumes duplicates are the same file. # # Django seems to already handle that. It appends datetime to the filename. # It means duplicated would be only for the same user who uploaded two files # with same name at the same second. if media_file: mtch = re.search(r'^([^/]+)/attachments/([^/]+)$', media_file) if mtch: # in cases where the media_file url created by instance.html's # _attachment_url function is in the wrong format, this will # match attachments with the correct owner and the same file name (username, filename) = mtch.groups() result = Attachment.objects.filter( instance__xform__user__username=username, ).filter( Q(media_file_basename=filename) | Q( media_file_basename=None, media_file__endswith='/' + filename ) )[0:1] else: # search for media_file with exact matching name result = Attachment.objects.filter(media_file=media_file)[0:1] try: attachment = result[0] except IndexError: media_file_logger.info('attachment not found') return HttpResponseNotFound(_(u'Attachment not found')) # Checks whether users are allowed to see the media file before giving them # the url xform = attachment.instance.xform if not request.user.is_authenticated(): # This is not a DRF view, but we need to honor things like # `DigestAuthentication` (ODK Briefcase uses it!) and # `TokenAuthentication`. Let's try all the DRF authentication # classes before giving up drf_request = rest_framework.request.Request(request) for auth_class in api_settings.DEFAULT_AUTHENTICATION_CLASSES: auth_tuple = auth_class().authenticate(drf_request) if auth_tuple is not None: # Is it kosher to modify `request`? Let's do it anyway # since that's what `has_permission()` requires... request.user = auth_tuple[0] # `DEFAULT_AUTHENTICATION_CLASSES` are ordered and the # first match wins; don't look any further break if not has_permission(xform, xform.user, request): return HttpResponseForbidden(_(u'Not shared.')) media_url = None if not attachment.mimetype.startswith('image'): media_url = attachment.media_file.url else: try: media_url = image_url(attachment, size) except: media_file_logger.error('could not get thumbnail for image', exc_info=True) if media_url: # We want nginx to serve the media (instead of redirecting the media itself) # PROS: # - It avoids revealing the real location of the media. # - Full control on permission # CONS: # - When using S3 Storage, traffic is multiplied by 2. # S3 -> Nginx -> User response = HttpResponse() default_storage = get_storage_class()() if not isinstance(default_storage, FileSystemStorage): # Double-encode the S3 URL to take advantage of NGINX's # otherwise troublesome automatic decoding protected_url = '/protected-s3/{}'.format(urlquote(media_url)) else: protected_url = media_url.replace(settings.MEDIA_URL, "/protected/") # Let nginx determine the correct content type response["Content-Type"] = "" response["X-Accel-Redirect"] = protected_url return response return HttpResponseNotFound(_(u'Error: Attachment not found'))
def get_medium_download_url(self, obj): if obj.mimetype.startswith('image'): return image_url(obj, 'medium')
def get_small_download_url(self, obj): if obj.mimetype.startswith('image'): return image_url(obj, 'small')