{"id":26104261,"url":"https://github.com/nodes-vapor/storage","last_synced_at":"2025-03-09T21:01:46.527Z","repository":{"id":63919319,"uuid":"73427509","full_name":"ml-archive/storage","owner":"ml-archive","description":"Eases the use of multiple storage and CDN services 🗄","archived":true,"fork":false,"pushed_at":"2020-10-08T09:45:36.000Z","size":371,"stargazers_count":66,"open_issues_count":2,"forks_count":13,"subscribers_count":8,"default_branch":"master","last_synced_at":"2025-03-03T15:01:50.158Z","etag":null,"topics":["brto","server-side-swift","storage","swift","upload","vapor","vapor-2"],"latest_commit_sha":null,"homepage":"","language":"Swift","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/ml-archive.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}},"created_at":"2016-11-10T22:50:42.000Z","updated_at":"2025-01-11T09:08:35.000Z","dependencies_parsed_at":"2023-01-14T14:00:18.984Z","dependency_job_id":null,"html_url":"https://github.com/ml-archive/storage","commit_stats":null,"previous_names":["ml-archive/storage","nodes-vapor/storage"],"tags_count":25,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ml-archive%2Fstorage","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ml-archive%2Fstorage/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ml-archive%2Fstorage/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ml-archive%2Fstorage/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ml-archive","download_url":"https://codeload.github.com/ml-archive/storage/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":242750785,"owners_count":20179257,"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":["brto","server-side-swift","storage","swift","upload","vapor","vapor-2"],"created_at":"2025-03-09T21:01:17.300Z","updated_at":"2025-03-09T21:01:46.507Z","avatar_url":"https://github.com/ml-archive.png","language":"Swift","funding_links":[],"categories":["Storage"],"sub_categories":[],"readme":"# Storage 🗄\n[![Swift Version](https://img.shields.io/badge/Swift-4.2-brightgreen.svg)](http://swift.org)\n[![Vapor Version](https://img.shields.io/badge/Vapor-3-30B6FC.svg)](http://vapor.codes)\n[![Circle CI](https://circleci.com/gh/nodes-vapor/storage/tree/master.svg?style=shield)](https://circleci.com/gh/nodes-vapor/storage)\n[![codebeat badge](https://codebeat.co/badges/58eeca2c-7b58-4aea-9b09-d80e3b79de19)](https://codebeat.co/projects/github-com-nodes-vapor-storage-master)\n[![codecov](https://codecov.io/gh/nodes-vapor/storage/branch/master/graph/badge.svg)](https://codecov.io/gh/nodes-vapor/storage)\n[![Readme Score](http://readme-score-api.herokuapp.com/score.svg?url=https://github.com/nodes-vapor/storage)](http://clayallsopp.github.io/readme-score?url=https://github.com/nodes-vapor/storage)\n[![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/nodes-vapor/storage/master/LICENSE)\n\nA package to ease the use of multiple storage and CDN services.\n\n\n##### Table of Contents\n* [Getting started](#getting-started-)\n* [Upload a file](#upload-a-file-)\n  * [Base 64 and data URI](#base-64-and-data-uri-)\n* [Download a file](#download-a-file-)\n* [Get CDN path](#get-cdn-path-)\n* [Delete a file](#delete-a-file-)\n* [Configuration](#configuration-)\n  * [Network driver](#network-driver-)\n  * [Upload path](#upload-path-)\n\n\n## 📦 Installation\n\nAdd `Storage` to the package dependencies (in your `Package.swift` file):\n```swift\ndependencies: [\n    ...,\n    .package(url: \"https://github.com/nodes-vapor/storage.git\", from: \"1.0.0\")\n]\n```\n\nas well as to your target (e.g. \"App\"):\n\n```swift\ntargets: [\n    ...\n    .target(\n        name: \"App\",\n        dependencies: [... \"Storage\" ...]\n    ),\n    ...\n]\n```\n\n## Getting started 🚀\nStorage makes it easy to start uploading and downloading files. Just register a [network driver](#network-driver-) and get going.\n\n## Upload a file 🌐\n\nThere are a few different interfaces for uploading a file, the simplest being the following:\n```swift\nStorage.upload(\n    bytes: [UInt8],\n    fileName: String?,\n    fileExtension: String?,\n    mime: String?,\n    folder: String,\n    on container: Container \n) throws -\u003e String\n```\nThe aforementioned function will attempt to upload the file using your [selected driver and template](#configuration-) and will return a `String` representing the location of the file.\n\nIf you want to upload an image named `profile.png` your call site would look like:\n```swift\ntry Storage.upload(\n    bytes: bytes,\n    fileName: \"profile.png\",\n    on: req\n)\n```\n\n#### Base64 and data URI 📡\nIs your file a base64 or data URI? No problem!\n```swift\nStorage.upload(base64: \"SGVsbG8sIFdvcmxkIQ==\", fileName: \"base64.txt\", on: req)\nStorage.upload(dataURI: \"data:,Hello%2C%20World!\", fileName: \"data-uri.txt\", on: req)\n```\n\n#### Remote resources \nDownload an asset from a URL and then reupload it to your storage server.\n```swift\nStorage.upload(url: \"http://mysite.com/myimage.png\", fileName: \"profile.png\", on: req)\n```\n\n\n## Download a file ✅\n\nTo download a file that was previously uploaded you simply use the generated path.\n```swift\n// download image as `Foundation.Data`\nlet data = try Storage.get(\"/images/profile.png\", on: req)\n```\n\n\n## Get CDN path\n\nIn order to use the CDN path convenience, you'll have to set the CDN base url on Storage, e.g. in your `configure.swift` file:\n\n```swift\nStorage.cdnBaseURL = \"https://cdn.vapor.cloud\"\n```\n\nHere is how you generate the CDN path to a given asset.\n```swift\nlet cdnPath = try Storage.getCDNPath(for: path)\n```\n\nIf your CDN path is more involved than `cdnUrl` + `path`, you can build out Storage's optional completionhandler to override the default functionality.\n\n```swift\nStorage.cdnPathBuilder = { baseURL, path in\n    let joinedPath = (baseURL + path)\n    return joinedPath.replacingOccurrences(of: \"/images/original/\", with: \"/image/\")\n}\n```\n\n\n## Delete a file ❌\n\nDeleting a file can be done as follows.\n```swift\ntry Storage.delete(\"/images/profile.png\")\n```\n\n## Configuration ⚙\n\n`Storage` has a variety of configurable options.\n\n#### Network driver 🔨\nThe network driver is the module responsible for interacting with your 3rd party service. The default, and currently the only, driver is `s3`.\n```swift\nimport Storage\n\nlet driver = try S3Driver(\n    bucket: \"bucket\", \n    accessKey: \"access\",\n    secretKey: \"secret\"\n)\n\nservices.register(driver, as: NetworkDriver.self)\n```\n`bucket`, `accessKey`and `secretKey` are required by the S3 driver, while `template`, `host` and `region` are optional. `region` will default to `eu-west-1` and `host` will default to `s3.amazonaws.com`.\n\n#### Upload path 🛣\nA times, you may need to upload files to a different scheme than `/file.ext`. You can achieve this by passing in the `pathTemplate` parameter when creating the `S3Driver`. If the parameter is omitted it will default to `/#file`.\n\nThe following template will upload `profile.png` from the folder `images` to `/myapp/images/profile.png`\n```swift\nlet driver = try S3Driver(\n    bucket: \"mybucket\",\n    accessKey: \"myaccesskey\",\n    secretKey: \"mysecretkey\",\n    pathTemplate: \"/myapp/#folder/#file\"\n)\n```\n\n##### Aliases\nAliases are special keys in your template that will be replaced with dynamic information at the time of upload.\n\n *Note: if you use an alias and the information wasn't provided at the file upload's callsite, Storage will throw a `missingX`/`malformedX` error.*\n\n`#file`: The file's name and extension.\n\n```\nFile: \"test.png\"\nReturns: test.png\n```\n\n---\n\n`#fileName`: The file's name.\n\n```\nFile: \"test.png\"\nReturns: test\n```\n\n---\n\n`#fileExtension`: The file's extension.\n\n```\nFile: \"test.png\"\nReturns: png\n```\n\n---\n\n`#folder`: The provided folder.\n\n```\nFile: \"uploads/test.png\"\nReturns: uploads\n```\n\n---\n\n`#mime`: The file's content type.\n\n```\nFile: \"test.png\"\nReturns: image/png\n```\n\n---\n\n`#mimeFolder`: A folder generated according to the file's mime.\n\nThis alias will check the file's mime and if it's an image, it will return `images/original` else it will return `data`\n\n```\nFile: \"test.png\"\nReturns: images/original\n```\n\n---\n\n`#day`: The current day.\n\n```\nFile: \"test.png\"\nDate: 12/12/2012\nReturns: 12\n```\n\n---\n\n`#month`: The current month.\n\n```\nFile: \"test.png\"\nDate: 12/12/2012\nReturns: 12\n```\n\n---\n\n`#year`: The current year.\n\n```\nFile: \"test.png\"\nDate: 12/12/2012\nReturns: 2012\n```\n\n---\n\n`#timestamp`: The time of upload.\n\n```\nFile: \"test.png\"\nTime: 17:05:00\nReturns: 17:05:00\n```\n\n---\n\n`#uuid`: A generated UUID.\n\n ```\nFile: \"test.png\"\nReturns: 123e4567-e89b-12d3-a456-426655440000\n```\n\n---\n## 🏆 Credits\n\nThis package is developed and maintained by the Vapor team at [Nodes](https://www.nodesagency.com).\n\n## 📄 License\n\nThis package is open-sourced software licensed under the [MIT license](http://opensource.org/licenses/MIT)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnodes-vapor%2Fstorage","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnodes-vapor%2Fstorage","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnodes-vapor%2Fstorage/lists"}