2
0
mirror of https://github.com/inventree/InvenTree.git synced 2025-06-13 10:35:40 +00:00

Add the ability to extract image URL information when drag-and-dropping image URL from a browser window

- Can't do anything with it yet...
- Code is almost there but leaving for now
This commit is contained in:
Oliver Walters
2019-05-07 00:04:35 +10:00
parent 3c7238f29c
commit fe4acd48a7
5 changed files with 113 additions and 47 deletions

View File

@ -4,6 +4,7 @@ Provides helper functions used throughout the InvenTree project
import io import io
import json import json
import os.path
from datetime import datetime from datetime import datetime
from PIL import Image from PIL import Image
@ -20,6 +21,19 @@ def TestIfImage(img):
return False return False
def TestIfImageURL(url):
""" Test if an image URL (or filename) looks like a valid image format.
Simply tests the extension against a set of allowed values
"""
return os.path.splitext(os.path.basename(url))[-1].lower() in [
'.jpg', '.jpeg',
'.png', '.bmp',
'.tif', '.tiff',
'.webp',
]
def str2bool(text, test=True): def str2bool(text, test=True):
""" Test if a string 'looks' like a boolean value. """ Test if a string 'looks' like a boolean value.

View File

@ -106,37 +106,29 @@
var transfer = event.originalEvent.dataTransfer; var transfer = event.originalEvent.dataTransfer;
var formData = new FormData();
if (isFileTransfer(transfer)) { if (isFileTransfer(transfer)) {
formData.append('image_file', transfer.files[0]);
var file = transfer.files[0];
inventreeFileUpload(
"{% url 'part-image-upload' part.id %}",
file,
{},
{
success: function(data, status, xhr) {
location.reload();
},
error: function(xhr, status, error) {
showAlertDialog('Error uploading image', renderErrorMessage(xhr));
}
}
);
} else if (isOnlineTransfer(transfer)) { } else if (isOnlineTransfer(transfer)) {
formData.append('image_url', getImageUrlFromTransfer(transfer));
getImageUrlFromTransfer(transfer);
/*
for (var i = 0; i < 12; i++) {
transfer.items[i].getAsString(function(text) {
console.log('item ' + i + ' - ' + text);
});
}
*/
} else { } else {
console.log('Unknown transfer'); console.log('Unknown transfer');
return;
} }
inventreeFormDataUpload(
"{% url 'part-image-upload' part.id %}",
formData,
{
success: function(data, status, xhr) {
location.reload();
},
error: function(xhr, status, error) {
showAlertDialog('Error uploading image', renderErrorMessage(xhr));
}
}
);
}); });
$("#show-qr-code").click(function() { $("#show-qr-code").click(function() {

View File

@ -7,6 +7,9 @@ from __future__ import unicode_literals
from django.shortcuts import get_object_or_404 from django.shortcuts import get_object_or_404
from django.core.validators import URLValidator
from django.core.exceptions import ValidationError
from django.http import JsonResponse from django.http import JsonResponse
from django.urls import reverse_lazy from django.urls import reverse_lazy
from django.views.generic import DetailView, ListView from django.views.generic import DetailView, ListView
@ -30,7 +33,7 @@ from .forms import EditSupplierPartForm
from InvenTree.views import AjaxView, AjaxCreateView, AjaxUpdateView, AjaxDeleteView from InvenTree.views import AjaxView, AjaxCreateView, AjaxUpdateView, AjaxDeleteView
from InvenTree.views import QRCodeView from InvenTree.views import QRCodeView
from InvenTree.helpers import DownloadFile, str2bool, TestIfImage from InvenTree.helpers import DownloadFile, str2bool, TestIfImage, TestIfImageURL
class PartIndex(ListView): class PartIndex(ListView):
@ -270,7 +273,20 @@ class PartImage(AjaxUpdateView):
class UploadPartImage(AjaxView): class UploadPartImage(AjaxView):
""" View for uploading a Part image """ """ View for uploading a Part image via AJAX request.
e.g. via a "drag and drop" event.
There are two ways to upload a file:
1. Attach an image file as request.FILES['image_file']
- Image is validated saved
- Part object is saved
2. Attach an iamge URL as request.POST['image_url']
NOT YET IMPLEMENTED
- Image URL is valiated
- Image is downloaded and validated
- Part object is saved
"""
model = Part model = Part
@ -285,18 +301,63 @@ class UploadPartImage(AjaxView):
response['error'] = 'Part not found' response['error'] = 'Part not found'
return JsonResponse(error_dict, status=404) return JsonResponse(error_dict, status=404)
uploaded_file = request.FILES['file'] # Direct image upload
if 'image_file' in request.FILES:
image = request.FILES['image_file']
if TestIfImage(uploaded_file): if TestIfImage(image):
part.image = uploaded_file part.image = image
part.clean() part.clean()
part.save() part.save()
response['success'] = 'File was uploaded successfully' response['success'] = 'File was uploaded successfully'
else: status = 200
response['error'] = 'Not a valid image file' else:
status = 400 response['error'] = 'Not a valid image file'
status = 400
return JsonResponse(response, status=status)
elif 'image_url' in request.POST:
image_url = request.POST['image_url']
validator = URLValidator()
try:
validator(image_url)
except ValidationError:
response['error'] = 'Invalid image URL'
response['url'] = image_url
return JsonResponse(response, status=400)
# Test the the URL at least looks like an image
if not TestIfImageURL(image_url):
response['error'] = 'Invalid image URL'
return JsonResponse(response, status=400)
response['error'] = 'Cannot download cross-site images (yet)'
response['url'] = image_url
response['apology'] = 'deepest'
return JsonResponse(response, status=400)
# TODO - Attempt to download the image file here
"""
head = requests.head(url, stream=True, headers={'User-agent': 'Mozilla/5.0'})
if head.headers['Content-Length'] < SOME_MAX_LENGTH:
image = requests.get(url, stream=True, headers={'User-agent': 'Mozilla/5.0'})
file = io.BytesIO(image.raw.read())
- Save the file?
"""
# Default response
return JsonResponse(response, status=status) return JsonResponse(response, status=status)

View File

@ -42,8 +42,8 @@ function inventreeGet(url, filters={}, options={}) {
}); });
} }
function inventreeFileUpload(url, file, data={}, options={}) { function inventreeFormDataUpload(url, data, options={}) {
/* Upload a file via AJAX using the FormData approach. /* Upload via AJAX using the FormData approach.
* *
* Note that the following AJAX parameters are required for FormData upload * Note that the following AJAX parameters are required for FormData upload
* *
@ -53,10 +53,6 @@ function inventreeFileUpload(url, file, data={}, options={}) {
// CSRF cookie token // CSRF cookie token
var csrftoken = getCookie('csrftoken'); var csrftoken = getCookie('csrftoken');
var data = new FormData();
data.append('file', file);
return $.ajax({ return $.ajax({
beforeSend: function(xhr, settings) { beforeSend: function(xhr, settings) {
@ -68,14 +64,13 @@ function inventreeFileUpload(url, file, data={}, options={}) {
processData: false, processData: false,
contentType: false, contentType: false,
success: function(data, status, xhr) { success: function(data, status, xhr) {
console.log('Uploaded file - ' + file.name); console.log('Form data upload success');
if (options.success) { if (options.success) {
options.success(data, status, xhr); options.success(data, status, xhr);
} }
}, },
error: function(xhr, status, error) { error: function(xhr, status, error) {
console.log('Error uploading file: ' + status); console.log('Form data upload failure: ' + status);
if (options.error) { if (options.error) {
options.error(xhr, status, error); options.error(xhr, status, error);

View File

@ -58,5 +58,9 @@ function getImageUrlFromTransfer(transfer) {
/* Extract external image URL from a drag-and-dropped image /* Extract external image URL from a drag-and-dropped image
*/ */
console.log(transfer.getData('text/html').match(/src\s*=\s*"(.+?)"/)[1]); var url = transfer.getData('text/html').match(/src\s*=\s*"(.+?)"/)[1];
console.log('Image URL: ' + url);
return url;
} }