expected str, bytes or os.PathLike object, not InMemoryUploadedFile

28.6k views Asked by At

I have a method to read a Newick file and return a String in Django framework which is the following:

def handle_uploaded_file(f):
    output = " "
    for chunk in f.chunks():
        output += chunk.decode('ascii')
    return output.replace("\n", "").replace("\r", "")


def post(self, request):
    form = HomeForm(request.POST, request.FILES)
    if form.is_valid():
        input = handle_uploaded_file(request.FILES['file'])
        treeGelezen = Tree(input, format=1)
        script, div = mainmain(treeGelezen)
        form = HomeForm()
    args = {'form': form, 'script': script, 'div': div}
    return render(request, self.template_name, args)

Which works fine for normal Newick files but i also have some files which have a string at the beginning of the file. I'm trying to make another method which checks if the file has the following String before it (which is the case in some files): "newick;" and removes the string if found. It works locally but i can't seem to merge them. This is how it locally looks like:

def removeNewick(tree_with_newick):
    for x in tree_with_newick:
        if x.startswith('newick;'):
            print('')
    return x


filepath = "C:\\Users\\msi00\\Desktop\\ncbi-taxanomy.tre"
tree_with_newick = open(filepath)
tree = Tree(newick=removeNewick(tree_with_newick), format=1)

which works perfectly when i specify the path just in python so i tried combining them in Django like this:

def handle_uploaded_file(f):
    tree_with_newick = open(f)
    for x in tree_with_newick:
        if x.startswith('newick;'):
            print('')
    return cutFile(x)


def cutFile(f):
    output = " "
    for chunk in f.chunks():
        output += chunk.decode('ascii')
    return output.replace("\n", "").replace("\r", "")


def post(self, request):
    form = HomeForm(request.POST, request.FILES)
    if form.is_valid():
        input = handle_uploaded_file(request.FILES['file'])
        treeGelezen = Tree(input, format=1)
        script, div = mainmain(treeGelezen)
        form = HomeForm()
    args = {'form': form, 'script': script, 'div': div}
    return render(request, self.template_name, args)

Which doesn't work and it gives the following error:

expected str, bytes or os.PathLike object, not InMemoryUploadedFile

I've been working on it for two days already and couldn't figure out why the error is popping up.

4

There are 4 answers

3
Will Keeling On BEST ANSWER

The error is happening because the function handle_uploaded_file(f) is trying to open an already opened file.

The value of request.FILES['file'] is a InMemoryUploadedFile and can be used like a normal file. You don't need to open it again.

To fix, just remove the line that tries to open the file:

def handle_uploaded_file(f):
    for x in f:
        if x.startswith('newick;'):
            print('')
    return cutFile(x)
0
Pooja On

Save the InMemoryUploadedFile to a temporary file.

you can save the InMemoryUploadedFile to a temporary file and then read the data from that file.

import tempfile

if input:
    with tempfile.NamedTemporaryFile(delete=False) as temp_file:
        temp_file.write(input.read())
        temp_file.close()

    with open(temp_file.name, 'r') as file:
        image_data = file.read()
0
Deniz On

the solution for me;

MEDIA_ROOT = os.path.join(BASE_DIR, 'media')

instead of :

MEDIA_ROOT = [os.path.join(BASE_DIR, 'media')]

in settigs.py

0
Richard E Long On

In my setting.py I had

MEDIA_ROOT = os.path.join(BASE_DIR, 'media'),

when it should've been

MEDIA_ROOT = os.path.join(BASE_DIR, 'media')

which solved this error for me.