MerginMaps / MerginMaps/media-sync
MinIO driver uploads files without Content-Type → all files get application/octet-stream
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 8
- Forks
- 9
- PR merge metrics
- No merged PRs in 30d
Description
Description
The MinIO driver uploads all media files without setting the content_type
parameter. As a result, MinIO falls back to its default value
application/octet-stream for every object — regardless of whether the file
is a JPEG, PNG, PDF, MP4 or anything else.
This causes problems whenever the bucket is consumed by clients that rely on
the HTTP Content-Type header to render the content inline:
- Browsers offer the file as a download instead of displaying it
- QGIS HTML widgets / map tips cannot render
<img>references to the bucket - Embedding photos in WebGIS / popups / reports requires a workaround
- The MinIO response additionally includes
X-Content-Type-Options: nosniff,
which prevents clients from guessing the type from the payload
A typical response header for an uploaded JPG currently looks like this:
content-type: application/octet-stream
x-content-type-options: nosniff
content-length: 326330
Even though the file is a perfectly valid JPEG.
Reproduction
-
Set up media-sync with a MinIO backend (driver:
minio) -
Sync a Mergin Maps project that contains photos (e.g. captured with the
Mergin Maps mobile app) -
Inspect the response headers of any uploaded file in the bucket, e.g.:
curl -I https://<minio-host>/<bucket>/fotos/example.jpgResult:
Content-Type: application/octet-stream
Root cause
In drivers.py, the MinioDriver.upload_file() method calls
fput_object() without a content_type:
res = self.client.fput_object(self.bucket, obj_path, src)
The default for that parameter in the MinIO Python SDK is
application/octet-stream, so every object ends up with that type.
Proposed fix
Use Python's standard mimetypes module to derive the type from the file
extension, falling back to the previous default if unknown:
import mimetypes
def upload_file(self, src, obj_path):
if self.bucket_subpath:
obj_path = f"{self.bucket_subpath}/{obj_path}"
try:
content_type, _ = mimetypes.guess_type(src)
if content_type is None:
content_type = "application/octet-stream"
res = self.client.fput_object(
self.bucket, obj_path, src, content_type=content_type
)
dest = self.base_url + "/" + res.object_name
except S3Error as e:
raise DriverError("MinIO driver error: " + str(e))
return dest
This is a minimal, dependency-free change (mimetypes is part of the Python
standard library) that fixes the issue for all common media file types
produced by Mergin Maps (jpg, jpeg, png, heic, mp4, pdf, …).
I'm happy to open a PR if that helps.
Environment
- media-sync: latest
main - Backend: MinIO (S3-compatible)
- Mergin Maps cloud
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in drivers.py at MinioDriver.upload_file() and inspect how the existing fput_object() call is built. Reproduce the issue with the provided MinIO setup and curl request, then verify that uploads receive their detected media type while unknown extensions retain application/octet-stream.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- backend
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 86/100