How to read a jpeg from disk and instantiate it as 'werkzeug.datastructures.FileStorage'?

62 Views Asked by At
python  3.10.11
werkzeug  2.3.7

I have a jpeg in /mnt/dragon.jpeg

I want to write unit test for a method, which has werkzeug.datastructures.FileStorage as input, and behavior is save it to a path.

I try to instantiate it with codes below:

import os
from werkzeug.datastructures import FileStorage

PATH = "/mnt/dragon.jpeg"

def get_file(filepath: str) -> FileStorage:
    filename = os.path.basename(filepath)
    with open(filepath, 'rb') as file:
        return FileStorage(file, name=filename)

file = get_file(PATH)

The ipython instance output are:

In [8]: file
Out[8]: <FileStorage: '/mnt/dragon.jpeg' (None)>

In [9]: file.save("/mnt/saved.jpeg")
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In[9], line 1
----> 1 file.save("/mnt/saved.jpeg")

File ~/.local/lib/python3.10/site-packages/werkzeug/datastructures/file_storage.py:129, in FileStorage.save(self, dst, buffer_size)
    126     close_dst = True
    128 try:
--> 129     copyfileobj(self.stream, dst, buffer_size)
    130 finally:
    131     if close_dst:

File ~/miniconda3/lib/python3.10/shutil.py:195, in copyfileobj(fsrc, fdst, length)
    193 fdst_write = fdst.write
    194 while True:
--> 195     buf = fsrc_read(length)
    196     if not buf:
    197         break

ValueError: read of closed file

How to make the werkzeug.datastructures.FileStorage file can be saved outside the scope of open?

2

There are 2 best solutions below

1
user459872 On BEST ANSWER

You can use in-memory bytes buffer(io.BytesIO). The current problem with your code is that python closes the underlying file as soon as the with block completes its execution.

import os
import io
from werkzeug.datastructures import FileStorage

PATH = "/mnt/dragon.jpeg"

def get_file(filepath: str) -> FileStorage:
    filename = os.path.basename(filepath)
    with open(filepath, 'rb') as file:
        return FileStorage(io.BytesIO(file.read()), name=filename)

file = get_file(PATH)
2
stevezkw On
def get_file(filepath: str) -> FileStorage:
    filename = os.path.basename(filepath)
    file = open(filepath, 'rb')
    return FileStorage(file, name=filename)

Changing function to this solved this issue