# [PGN Trading] File Storage Integration (WM-525)
## File Naming Rule
- [File Storage Hierarchy](/e2a1aqfMQ7KnNpqBYBvP4A)
---
## File Storage Service
==accepted file type==
- image: `jpg`/`jpeg`, `png`, `heic`, `tiff`/`tif`
- PDF: `pdf`
### wrapped function: `upload_file()`
1. convert data url to binary: `binascii.a2b_base64()`
2. detect file type: `filetype.guess()`
3. call put-file-function
- `put_transaction_document()`
### `put_transaction_document()`
- put object to MinIO by `content_type`
```python=
from binascii import a2b_base64
import filetype
from gf.service.file_storage import MinioFileStorageService
...
async def upload_file(
data_url=data_url,
customer_id=customer_id,
transaction_document_code,
filename=filename,
):
# convert data url to binary
with open(data_url) as f:
data = f.read()
binary_data = a2b_base64(data)
# detect file type
content_type = filetype.guess(binary_data)
# put object to MinIO
version_id = await put_transaction_document(
customer_id=customer_id,
transaction_document_code=transaction_document_code,
file=binary_data,
content_type=content_type,
filename=filename,
)
...
file_storage_service = get_file_storage_service(FileStorageSettings)
def __get_transaction_document_object_name(
customer_id: str, transaction_document_code: str
) -> str:
return f'{TRANSACTION_DOCUMENT_PREFIX}{customer_id}/{transaction_document_code}'
async def put_transaction_document(
customer_id: str,
transaction_document_code: str,
file: IO,
content_type: str,
filename: Optional[str] = None,
) -> str:
return await file_storage_service.put_object(
{BUCKET_NAME},
__get_transaction_document_object_name(
customer_id, transaction_document_code
),
file,
content_type,
metadata,
)
```
### `get_transaction_document()`
- get transaction document by `customer_id` & `version_id`
```python=
def get_transaction_document():
return file_storage_service.get_object(
object_name=__get_transaction_document_object_name(
customer_id, transaction_document_code
),
version_id=version_id,
)
```