Test that uploaded image is an image file, return error otherwise

- New javascript function inventreeFileUpload
This commit is contained in:
Oliver Walters 2019-05-06 22:20:06 +10:00
parent c88149b9aa
commit bb702367b6
8 changed files with 86 additions and 53 deletions

View File

@ -5,11 +5,21 @@ Provides helper functions used throughout the InvenTree project
import io import io
import json import json
from datetime import datetime from datetime import datetime
from PIL import Image
from wsgiref.util import FileWrapper from wsgiref.util import FileWrapper
from django.http import StreamingHttpResponse from django.http import StreamingHttpResponse
def TestIfImage(img):
""" Test if an image file is indeed an image """
try:
Image.open(img).verify()
return True
except:
return False
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

@ -78,7 +78,6 @@ class EditPartForm(HelperForm):
'purchaseable', 'purchaseable',
'salable', 'salable',
'notes', 'notes',
'image',
] ]

View File

@ -153,7 +153,7 @@
{ {
accept_text: 'Activate', accept_text: 'Activate',
accept: function() { accept: function() {
inventreeUpdate( inventreePut(
"{% url 'api-part-detail' part.id %}", "{% url 'api-part-detail' part.id %}",
{ {
active: true, active: true,
@ -176,7 +176,7 @@
{ {
accept_text: 'Deactivate', accept_text: 'Deactivate',
accept: function() { accept: function() {
inventreeUpdate( inventreePut(
"{% url 'api-part-detail' part.id %}", "{% url 'api-part-detail' part.id %}",
{ {
active: false, active: false,

View File

@ -108,47 +108,22 @@
var files = transfer.files; var files = transfer.files;
console.log('dropped');
if (files.length > 0) { if (files.length > 0) {
var file = files[0]; var file = files[0];
var formData = new FormData(); inventreeFileUpload(
"{% url 'part-image-upload' part.id %}",
var token = getCookie('csrftoken'); file,
{},
formData.append('file', file); {
$.ajax({
beforeSend: function(xhr, settings) {
xhr.setRequestHeader('X-CSRFToken', token);
},
url: "{% url 'part-image-upload' part.id %}",
type: 'POST',
data: formData,
processData: false,
contentType: false,
success: function(data, status, xhr) { success: function(data, status, xhr) {
//location.reload(); location.reload();
}, },
error: function(xhr, status, error) { error: function(xhr, status, error) {
console.log('Error uploading thumbnail: ' + status); showAlertDialog('Error uploading image', renderErrorMessage(xhr));
console.log(error);
} }
});
/*
inventreeUpdate(
"{% url 'part-image-upload' part.id %}",
formData,
{
method: 'POST',
dataType: 'json',
} }
); );
*/
console.log('submitted');
} }
}); });

View File

@ -30,7 +30,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 from InvenTree.helpers import DownloadFile, str2bool, TestIfImage
class PartIndex(ListView): class PartIndex(ListView):
@ -275,22 +275,29 @@ class UploadPartImage(AjaxView):
model = Part model = Part
def post(self, request, *args, **kwargs): def post(self, request, *args, **kwargs):
response = {}
status = 200
try: try:
part = Part.objects.get(pk=kwargs.get('pk')) part = Part.objects.get(pk=kwargs.get('pk'))
except Part.DoesNotExist: except Part.DoesNotExist:
error_dict = { response['error'] = 'Part not found'
'error': 'Part not found',
}
return JsonResponse(error_dict, status=404) return JsonResponse(error_dict, status=404)
print("Files:", request.FILES)
uploaded_file = request.FILES['file'] uploaded_file = request.FILES['file']
response_dict = { if TestIfImage(uploaded_file):
'success': 'File was uploaded successfully', part.image = uploaded_file
} part.clean()
part.save()
return JsonResponse(response_dict, status=200) response['success'] = 'File was uploaded successfully'
else:
response['error'] = 'Not a valid image file'
status = 400
return JsonResponse(response, status=status)

View File

@ -42,7 +42,49 @@ function inventreeGet(url, filters={}, options={}) {
}); });
} }
function inventreeUpdate(url, data={}, options={}) { function inventreeFileUpload(url, file, data={}, options={}) {
/* Upload a file via AJAX using the FormData approach.
*
* Note that the following AJAX parameters are required for FormData upload
*
* processData: false
* contentType: false
*/
// CSRF cookie token
var csrftoken = getCookie('csrftoken');
var data = new FormData();
data.append('file', file);
return $.ajax({
beforeSend: function(xhr, settings) {
xhr.setRequestHeader('X-CSRFToken', csrftoken);
},
url: url,
method: 'POST',
data: data,
processData: false,
contentType: false,
success: function(data, status, xhr) {
console.log('Uploaded file - ' + file.name);
if (options.success) {
options.success(data, status, xhr);
}
},
error: function(xhr, status, error) {
console.log('Error uploading file: ' + status);
if (options.error) {
options.error(xhr, status, error);
}
}
});
}
function inventreePut(url, data={}, options={}) {
var method = options.method || 'PUT'; var method = options.method || 'PUT';
@ -93,9 +135,9 @@ function getCompanies(filters={}, options={}) {
} }
function updateStockItem(pk, data, final=false) { function updateStockItem(pk, data, final=false) {
return inventreeUpdate('/api/stock/' + pk + '/', data, final); return inventreePut('/api/stock/' + pk + '/', data, final);
} }
function updatePart(pk, data, final=false) { function updatePart(pk, data, final=false) {
return inventreeUpdate('/api/part/' + pk + '/', data, final); return inventreePut('/api/part/' + pk + '/', data, final);
} }

View File

@ -41,7 +41,7 @@ function toggleStar(options) {
if (response.length == 0) { if (response.length == 0) {
// Zero length response = star does not exist // Zero length response = star does not exist
// So let's add one! // So let's add one!
inventreeUpdate( inventreePut(
url, url,
{ {
part: options.part, part: options.part,
@ -57,7 +57,7 @@ function toggleStar(options) {
} else { } else {
var pk = response[0].pk; var pk = response[0].pk;
// There IS a star (delete it!) // There IS a star (delete it!)
inventreeUpdate( inventreePut(
url + pk + "/", url + pk + "/",
{ {
}, },

View File

@ -141,7 +141,7 @@ function updateStock(items, options={}) {
return false; return false;
} }
inventreeUpdate("/api/stock/stocktake/", inventreePut("/api/stock/stocktake/",
{ {
'action': options.action, 'action': options.action,
'items[]': stocktake, 'items[]': stocktake,
@ -226,7 +226,7 @@ function moveStockItems(items, options) {
} }
function doMove(location, parts, notes) { function doMove(location, parts, notes) {
inventreeUpdate("/api/stock/move/", inventreePut("/api/stock/move/",
{ {
location: location, location: location,
'parts[]': parts, 'parts[]': parts,