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 json
from datetime import datetime
from PIL import Image
from wsgiref.util import FileWrapper
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):
""" Test if a string 'looks' like a boolean value.

View File

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

View File

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

View File

@ -108,47 +108,22 @@
var files = transfer.files;
console.log('dropped');
if (files.length > 0) {
var file = files[0];
var formData = new FormData();
var token = getCookie('csrftoken');
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) {
//location.reload();
},
error: function(xhr, status, error) {
console.log('Error uploading thumbnail: ' + status);
console.log(error);
}
});
/*
inventreeUpdate(
inventreeFileUpload(
"{% url 'part-image-upload' part.id %}",
formData,
file,
{},
{
method: 'POST',
dataType: 'json',
success: function(data, status, xhr) {
location.reload();
},
error: function(xhr, status, error) {
showAlertDialog('Error uploading image', renderErrorMessage(xhr));
}
}
);
*/
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 QRCodeView
from InvenTree.helpers import DownloadFile, str2bool
from InvenTree.helpers import DownloadFile, str2bool, TestIfImage
class PartIndex(ListView):
@ -275,22 +275,29 @@ class UploadPartImage(AjaxView):
model = Part
def post(self, request, *args, **kwargs):
response = {}
status = 200
try:
part = Part.objects.get(pk=kwargs.get('pk'))
except Part.DoesNotExist:
error_dict = {
'error': 'Part not found',
}
response['error'] = 'Part not found'
return JsonResponse(error_dict, status=404)
print("Files:", request.FILES)
uploaded_file = request.FILES['file']
response_dict = {
'success': 'File was uploaded successfully',
}
if TestIfImage(uploaded_file):
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';
@ -93,9 +135,9 @@ function getCompanies(filters={}, options={}) {
}
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) {
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) {
// Zero length response = star does not exist
// So let's add one!
inventreeUpdate(
inventreePut(
url,
{
part: options.part,
@ -57,7 +57,7 @@ function toggleStar(options) {
} else {
var pk = response[0].pk;
// There IS a star (delete it!)
inventreeUpdate(
inventreePut(
url + pk + "/",
{
},

View File

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