{"id":17891183,"url":"https://github.com/lekovr/fiwes","last_synced_at":"2026-05-02T03:32:25.929Z","repository":{"id":55640295,"uuid":"183710929","full_name":"LeKovr/fiwes","owner":"LeKovr","description":"file web storage","archived":false,"fork":false,"pushed_at":"2024-10-08T21:49:02.000Z","size":874,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-02-08T17:22:46.459Z","etag":null,"topics":["docker-image","golang","image-processing","storage"],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/LeKovr.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-04-27T00:43:01.000Z","updated_at":"2024-10-08T21:49:05.000Z","dependencies_parsed_at":"2023-11-22T02:26:18.302Z","dependency_job_id":"6d078e30-b27e-4dc8-bbbf-2668bf979144","html_url":"https://github.com/LeKovr/fiwes","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LeKovr%2Ffiwes","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LeKovr%2Ffiwes/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LeKovr%2Ffiwes/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LeKovr%2Ffiwes/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/LeKovr","download_url":"https://codeload.github.com/LeKovr/fiwes/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246928480,"owners_count":20856292,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["docker-image","golang","image-processing","storage"],"created_at":"2024-10-28T14:05:02.188Z","updated_at":"2026-05-02T03:32:25.891Z","avatar_url":"https://github.com/LeKovr.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# fiwes - File (Image) WEb Storage\n\n[![GoDoc][gd1]][gd2]\n [![codecov][cc1]][cc2]\n [![GoCard][gc1]][gc2]\n [![GitHub Release][gr1]][gr2]\n [![Docker Image][di1]][di2]\n [![LoC][loc1]][loc2]\n [![GitHub license][gl1]][gl2]\n\n[cc1]: https://codecov.io/gh/LeKovr/fiwes/branch/master/graph/badge.svg\n[cc2]: https://codecov.io/gh/LeKovr/fiwes\n[gd1]: https://godoc.org/github.com/LeKovr/fiwes?status.svg\n[gd2]: https://godoc.org/github.com/LeKovr/fiwes\n[gc1]: https://goreportcard.com/badge/github.com/LeKovr/fiwes\n[gc2]: https://goreportcard.com/report/github.com/LeKovr/fiwes\n[gr1]: https://img.shields.io/github/release/LeKovr/fiwes.svg\n[gr2]: https://github.com/LeKovr/fiwes/releases\n[di1]: https://img.shields.io/badge/docker-lekovr/fiwes-blue.svg\n[di2]: https://hub.docker.com/r/lekovr/fiwes/\n[loc1]: https://raw.githubusercontent.com/LeKovr/fiwes/master/.loc.svg?sanitize=true \"Lines of Code\"\n[loc2]: https://github.com/LeKovr/fiwes/blob/master/LOC.md\n[gl1]: https://img.shields.io/github/license/LeKovr/fiwes.svg\n[gl2]: https://github.com/LeKovr/fiwes/blob/master/LICENSE\n\n## Назначение\n\nПриложение, которое принимает по http изображения, сохраняет их и делает превью 100х100 пикселей.\n\nВходные данные: \n1. multipart/form-data\n2. строка base64 в JSON\n3. ссылка на изображение из сети как GET параметр\n\n### Дополнения\n\n1. test coverage \u003e= 70%\n2. поддержка деплоя командой `docker-compose up`\n\n## Особенности реализации\n\n* Т.к. список форматов изображений не задан (может, .svg?), принимаем, что список форматов аналогичен списку поддерживаемых выбранным пакетом ресайза ([imaging](https://github.com/disintegration/imaging))\n* Т.к. цель - прием изображений, то при получении файла, который не является изображением (т.е. пакет не может выполнить ресайз), возвращается статус 415 (UnsupportedMediaType)\n* В случаях, когда запрос не в JSON, сервер отвечает редиректом на превью. Для GET тоже, чтобы рефреш не повторял скачивание. По redirect url можно получить id изображения, отрезав префикс (заменив `/preview/` на `/img/`)\n* Статус ошибки должен соответствовать некоторому стандарту, использованы предварительные варианты\n\n## Архитектура\n\n* [fiwes](https://github.com/LeKovr/fiwes) - Вебсервер на основе [gin-gonic](http://github.com/gin-gonic/gin)\n* [upload](https://godoc.org/github.com/LeKovr/fiwes/upload) - прием и сохранение файла, создание preview с помощью [imaging](https://github.com/disintegration/imaging)\n* [ginupload](https://godoc.org/github.com/LeKovr/fiwes/ginupload) - привязка upload к [gin-gonic](http://github.com/gin-gonic/gin)\n\n## Деплой\n\n```\nwget https://raw.githubusercontent.com/LeKovr/fiwes/master/docker-compose.yml\ndocker-compose up\n```\nПосле запуска сервис доступен по адресу http://localhost:8080/.\n\n### Локальная сборка\n\n```\ngit clone https://github.com/LeKovr/fiwes.git\ncd fiwes\nmake up\n```\n\n## Опции\n\nПриложение поддерживает параметры конфигурации:\n```\n$ ./fiwes -h\nfiwes 0.0-dev. File web storage server\nUsage:\n  fiwes [OPTIONS]\n\nApplication Options:\n      --http_addr=          Http listen address (default: localhost:8080)\n      --upload_limit=       Upload size limit (Mb) (default: 8)\n      --html                Show html index page\n\nImage upload Options:\n      --img.download_limit= External image size limit (Mb) (default: 8)\n      --img.dir=            Image upload destination (default: data/img)\n      --img.preview_dir=    Preview image destination (default: data/preview)\n      --img.preview_width=  Preview image width (default: 100)\n      --img.preview_heigth= Preview image heigth (default: 100)\n      --img.random_name     Do not keep uploaded image filename\n      --img.path=           Image URL path (default: /img)\n      --img.upload_path=    Image upload URL path (default: /upload)\n      --img.preview_path=   Preview image URL path (default: /preview)\n\nHelp Options:\n  -h, --help                Show this help message\n```\n\n## Docker\n\nОбраз docker создается \"from scratch\" и для запуска контейнера используются следующие файлы хост-системы:\n* /etc/timezone, /etc/localtime - чтобы время в логах соответствовало серверному\n\nФайл /etc/mime.types копируется в контейнер при сборке, для задания соответствий Content-Type расширениям (см [mime](https://golang.org/pkg/mime/#TypeByExtension)).\n\nВсе операции с docker производятся через контейнер docker-compose.\n\nПриложение запускается в контейнере под пользователем nobody:nogroup и сохраняет файлы в `./var/data`. Чтобы создание файлов было доступно, перед стартом контейнера выполняется команда `mkdir -p -m 777 var/data/{img,preview}`.\n\n## Использование\n\nОсновные операции, которые можно проделать с исходным кодом проекта, собраны в [Makefile](Makefile). Для получения справки по доступным операциям используется команда:\n```\n$ make\n##\n## Available make targets\n##\n## Sources\n    run                Run from sources\n    build-all          Build app with checks\n    build              Build app\n    build-standalone   Build app used in docker from scratch\n    gen                Generate mocks\n    fmt                Format go sources\n    vet                Run vet\n    lint               Run linter\n    lint-more          Run more linters\n    cov                Run tests and fill coverage.out\n    cov-html           Open coverage report in browser\n    cov-clean          Clean coverage report\n## Docker\n    up                 Start service in container\n    down               Stop service\n    build-docker       Build docker image\n    clean-docker       Remove docker image \u0026 temp files\n    dc                 run docker-compose\n## Misc\n    cloc               Count lines of code (including tests) and update LOC.md\n    help               List Makefile targets\n\n```\n\n## Статусы ответа сервера\n\n### 200. OK\n* возвращается вместе с ответом в JSON при успешной загрузке изображения в base64\n\n### 302. Found\n* Редирект на превью, возвращается при загрузке изображения методом POST в \"multipart/form-data\"\n* Редирект на превью, возвращается при загрузке изображения методом GET\n\n### 400. BadRequest\n* данные не соответствуют формату \"multipart/form-data\"\n* JSON не соответствует структуре `{\"name\": .., \"data\":..}`\n* в форме не передано поле \"file\" в единственном числе\n* строка в base64 Не соответствует формату\n\n### 415. UnsupportedMediaType\n* Загруженный файл не может быть обработан как изображение\n* Не удалось определить расширение файла по переданному Content-Type\n\n### 500. InternalServerError\n* Ошибка на стороне сервиса, подробности записаны в журнал\n\n### 503. ServiceUnavailable\n* Ошибка загрузки изображения по URL\n* Статус ответа загрузки изображения по URL != 200\n\n## См. также\n\n* вебсервер - http://github.com/gin-gonic/gin\n* ресайз\n  * https://github.com/disintegration/imaging\n  * https://github.com/nfnt/resize\n  * https://github.com/anthonynsimon/bild\n  * https://github.com/disintegration/gift\n* аналоги\n  * https://github.com/h2non/imaginary\n  * https://github.com/aldor007/mort\n  * https://github.com/thoas/picfit\n\n### Варианты развития проекта\n\n* [ ] add example?\n* [ ] tests via docker?\n* [ ] main.go: leave main() only and add `//+build !test`?\n* [ ] create preview as symlink if image size is 100x100?\n* [ ] rate limit\n* [ ] HTTP Range, Conditional, Options requests\n* [ ] Compression, for incoming base64 atleast\n\n## License\n\nThe MIT License (MIT), see [LICENSE](LICENSE).\n\nCopyright (c) 2019 Aleksei Kovrizhkin \u003clekovr+fiwes@gmail.com\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flekovr%2Ffiwes","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flekovr%2Ffiwes","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flekovr%2Ffiwes/lists"}