[Django] #31833: Processing file from FileField in a valid form leads to "I/O operation on closed file" exception after posting

34 views
Skip to first unread message

Django

unread,
Jul 27, 2020, 11:04:48 AM7/27/20
to django-...@googlegroups.com
#31833: Processing file from FileField in a valid form leads to "I/O operation on
closed file" exception after posting
--------------------------------------+------------------------
Reporter: elmajax | Owner: nobody
Type: Bug | Status: new
Component: Forms | Version: 3.0
Severity: Normal | Keywords:
Triage Stage: Unreviewed | Has patch: 0
Needs documentation: 0 | Needs tests: 0
Patch needs improvement: 0 | Easy pickings: 0
UI/UX: 0 |
--------------------------------------+------------------------
After posting a form with a unique FileField, "I/O operation on closed
file" exception occurs. Code provoking the error is within the view. I
doubled checked that form is properly validated from view and validator.

Strangely the validator class (file is processed differently) doesn't
throw an "I/O operation on closed file" exception when file is converted
with io.TextIOWrapper and processed (see validators.py code below) and
work properly.

It seems that somehow file (in memory) is flushed right after being posted
without any mean to process it further with form.is_valid().

Tested on Django 2.2.25 and 3.0.8.

**forms.py**

{{{

from .validators import CsvFileValidator

class FileImportForm(forms.Form):
headers =
["lastname","firstname","gender","title","entity","email","company","address","phone"]
file = forms.FileField(label='CSV
file',validators=[CsvFileValidator(headers)])

def clean_file(self):
file = self.cleaned_data['file']
return file
}}}

**views.py**

{{{
@login_required
def file_import(request):
if request.method == 'POST':
form = FileImportForm(request.POST,request.FILES)

if form.is_valid():
if request.FILES['file']:
file_post = request.FILES['file']
# Offending line below (I/O operation on closed file)
file_content = file_post.read().decode('UTF-8')

return redirect("/foo")
else:
form = FileImportForm()

return render(request,"file_import.html", { 'form': form })
}}}

**validators.py**

{{{
import csv

class CsvFileValidator(object):

def __init__(self, headers):
self.headers = headers

def __call__(self,file):

file_extension = os.path.splitext(file.name)[1]
valid_extensions = [ ".csv", ".CSV"]

if not file_extension.lower() in valid_extensions:
msg = "Invalid file extension"
logger.error(msg)
raise ValidationError("{}".format(msg), code='invalid')

try:
csv_file = io.TextIOWrapper(file)
csv_format = csv.Sniffer().sniff(csv_file.read(1024))
csv_file.seek(0,0)
except csv.Error:
msg = "Invalid CSV file"
logger.error(msg)
logger.debug("Exception msg : {}".format(msg))

raise ValidationError("{}".format(msg), code='invalid')

csv_reader = csv.reader(csv_file.read().splitlines(),
dialect=csv_format,delimiter=";")

for r_index, row in enumerate(csv_reader):

if r_index == 0:
if sorted(self.headers) != sorted(row):
msg = "Invalid or missing CSV headers"
logger.error(msg)

raise ValidationError("{}".format(msg),
code='invalid')

if not "".join(str(field) for field in row):
continue

msg = "Valid CSV file"
logger.debug(msg)

return True

def __eq__(self,other):
return (
isinstance(other, self.__class__)
and self.headers == other.headers
)
}}}

--
Ticket URL: <https://code.djangoproject.com/ticket/31833>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

Django

unread,
Jul 27, 2020, 11:48:47 AM7/27/20
to django-...@googlegroups.com
#31833: Processing file from FileField in a valid form leads to "I/O operation on
closed file" exception after posting
-------------------------+-------------------------------------------
Reporter: elmajax | Owner: Harpreet Sharma
Type: Bug | Status: assigned
Component: Forms | Version: 3.0
Severity: Normal | Resolution:

Keywords: | Triage Stage: Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------+-------------------------------------------
Changes (by Harpreet Sharma):

* owner: nobody => Harpreet Sharma
* status: new => assigned


--
Ticket URL: <https://code.djangoproject.com/ticket/31833#comment:1>

Django

unread,
Jul 27, 2020, 12:36:37 PM7/27/20
to django-...@googlegroups.com
#31833: Processing file from FileField with a custom class-based validator in a

valid form leads to "I/O operation on closed file" exception after posting
-------------------------+-------------------------------------------
Reporter: elmajax | Owner: Harpreet Sharma
Type: Bug | Status: assigned
Component: Forms | Version: 3.0
Severity: Normal | Resolution:

Keywords: | Triage Stage: Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------+-------------------------------------------

--
Ticket URL: <https://code.djangoproject.com/ticket/31833#comment:2>

Django

unread,
Jul 28, 2020, 1:02:55 AM7/28/20
to django-...@googlegroups.com
#31833: FileField with a custom validator leads to "I/O operation on closed file".

-------------------------+-------------------------------------------
Reporter: elmajax | Owner: Harpreet Sharma
Type: Bug | Status: closed
Component: Forms | Version: 3.0
Severity: Normal | Resolution: invalid

Keywords: | Triage Stage: Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------+-------------------------------------------
Changes (by felixxm):

* status: assigned => closed
* resolution: => invalid


Comment:

Please don't use trac as a support channel. Everything works properly with
a stub `CsvFileValidator`:
{{{
class CsvFileValidator:
def __call__(self,file):
return True
}}}
so it's not an issue in Django but in your implementation.

Closing per TicketClosingReasons/UseSupportChannels.

--
Ticket URL: <https://code.djangoproject.com/ticket/31833#comment:3>

Reply all
Reply to author
Forward
0 new messages