In core.files.storage, the storage object doesn't check the length of filename + upload_to to ensure that it's less than 100 characters. If the path length is greater than 100, it is truncated to 100 characters when inserted into the database. With filename collision mitigation appending an '_' to the end of the filename, popular filenames can easily reach lengths that exceed the size of the.
To reproduce the issue, try uploading a file/image with a length over 100 characters.
Here's some quick hackery that attempts truncate the filename. Note that it assumes the upload_to length to be less than 30 characters long. Also note that this should probably be divided up into a couple of different methods and this is more to get the ball rolling than anything.
def get_available_name(self, name):
Returns a filename that's free on the target storage system, and
available for new content to be written to.
# If the filename already exists, append an incrementing integer
# to the file until the filename doesn't exist.
dir_name, file_name = os.path.split(name)
flength = len(file_name)
if flength > 70: # If filenameis longer than 70, truncate filename
offset = flength - (flength % 40 + 20) # modulus of file name + 20 to prevent file type truncation
file_name = file_name[offset:]
name = os.path.join(dir_name, file_name)
if self.exists(name): # filename exists, get dot index
dot_index = file_name.rindex('.')
except ValueError: # filename has no dot
dot_index = -1
inc = 0 # Set incrementer to zero
inc += 1
if dot_index == -1: # If no dot, append to end
tname = file_name + str(inc)
tname = file_name[:dot_index] + str(inc) + file_name[dot_index:]
name = os.path.join(dir_name, tname)