# Upload & Download Objects from a Bucket

import DocButton from '~/components/webkit/DocButton.vue';

Azion **Object Storage** allows you to create buckets, store and manage data at the Edge, and integrate your object storage with your edge infrastructure in a simple way — the fastest way to get started is using the **Azion Console**, but you can also automate processes via API or Azion Runtime; this guide covers how to upload and download objects from a bucket using the Console, the [Azion API](https://api.azion.com) and [Azion Runtime](/en/documentation/runtime/api-reference/storage/).

<DocButton href="/en/documentation/products/store/object-storage/" label="go to Object Storage reference" kind="secondary" size="medium" />

Read [How to create and modify an Object Storage bucket](/en/documentation/products/guides/create-and-modify-bucket/) for bucket operations.

---

## Get started in 30 seconds (via Console)

The graphical interface is ideal for quick uploads and initial configurations.

1. **Access the Console:** Navigate to the [Object Storage](https://console.azion.com/object-storage) menu.
2. **Create your Bucket:** Click **+ Bucket**.
   - **Name:** Choose a unique name.
   - **Workloads Access:** Select how the Azion network will access the data. We recommend **Read Only** to serve static content.

3. **Upload:** Enter the created bucket and drag your files directly to the interface or use the upload button.

Done! Your files are now on Azion's global infrastructure. The next step is to [configure a Workload to deliver this content with Edge performance](https://www.azion.com/en/documentation/products/guides/use-bucket-as-origin/).


---

## Via API

Azion's Object Storage is fully exposed via [Azion API v4](https://api.azion.com). The Azion Console consumes these APIs, so all actions available in the Console can be executed directly via API, enabling complete automation.

This allows integrating Object Storage into CI/CD pipelines, automated routines, and applications, without dependency on the graphical interface.

1. Create a token for access in the **Personal token** menu in Azion Console: https://console.azion.com/personal-tokens.

2. **Create a bucket** named `statics_test`.

```bash
   curl --request POST \
     --url https://api.azion.com/v4/workspace/storage/buckets \
     --header 'Accept: application/json' \
     --header 'Authorization: Token AZION_PERSONAL_TOKEN' \
     --header 'Content-Type: application/json' \
     --data '{
     "name": "statics_test",
     "workloads_access": "read_only"
   }'
```

3. **Upload objects.**

```bash
   curl --request POST \
     --url https://api.azion.com/v4/workspace/storage/buckets/statics_test/objects/logo.svg \
     --header 'Accept: application/json' \
     --header 'Authorization: Token AZION_PERSONAL_TOKEN' \
     --header 'Content-Type: application/octet-stream' \
     --data @logo.svg
```

4. **List objects.**

```bash
   curl --request GET \
     --url https://api.azion.com/v4/workspace/storage/buckets/statics_test/objects \
     --header 'Accept: application/json' \
     --header 'Authorization: Token AZION_PERSONAL_TOKEN'
```


## Download an object from a bucket

To download an object, run the following `GET` request in your terminal, replacing `[TOKEN VALUE]` with your [personal token](/en/documentation/products/guides/personal-tokens/), `<bucket_name>` with the name of your bucket, and `<object_key>` with the key created for the object:

```bash
curl --location 'https://api.azion.com/v4/storage/buckets/<bucket_name>/objects/<object_key>' \
--header 'Accept: application/json; version=3' \
--header 'Authorization: Token [TOKEN VALUE]'
```

You should now see the contents of the object in your terminal.

:::note
To download the object to your device locally, add the cURL options `-O` to use the header-provided object name and `-J` to write the output into a file.

```bash
curl --location 'https://api.azion.com/v4/storage/buckets/<bucket_name>/objects/<object_key> -O -J' \
--header 'Accept: application/json; version=3' \
--header 'Authorization: Token [TOKEN VALUE]'
```

When working with files that have a prefix in the object key, like `folder/file.csv`, using these options won't create a new directory. Instead, the file will be downloaded directly to the root folder where the command was initiated.
:::

---

## Via Azion Runtime

You can create a function to upload files to your bucket using a `POST` console command and verify if a file is available using a `GET` console command. To do so:

1. Access [Azion Console](/en/documentation/products/guides/how-to-access-azion-console/) > **Functions**.
2. Click the **Add Function** button.
3. Name your function. Example: `my-bucket POST+GET`.
4. In the **Code** tab, add the following JavaScript code:

```js
import Storage from "azion:storage";
async function doGet(path, bucket_name) {
    console.log(`Path: ${path}`);
    const storage = new Storage(bucket_name);
    // content is an StorageObject
    const asset = await storage.get(path);
    return new Response(await asset.arrayBuffer(), {
        headers: {
            "Content-Type": asset.contentType
        },
    });
}

async function doPost(path, content_type, value, bucket_name) {
    console.log(`Path: ${path}`);
    let options = {
        "Content-Type": content_type
    }
    console.log(`Options: ${options}`);
    const storage = new Storage(bucket_name);
    await storage.put(path, value, options);
    return new Response("Object added.");
}

async function router(event) {
    const request = event.request;
    const method = request.method;
    const path = decodeURI(new URL(request.url).pathname);
    const bucket_name = event.args.bucket;
    if (method === "POST") {
        let content_type = request.headers.get("Content-Type");
        let content = await request.arrayBuffer();
        return doPost(path, content_type, content, bucket_name);
    } else if (method === "GET") {
        return doGet(path, bucket_name);
    } else {
        throw new Error(`Invalid method: ${method}. Expected POST or GET.`);
    }
}
addEventListener("fetch", (event) => {
    event.respondWith(
        router(event)
    );
});
```

| Variable | Description |
| --- | --- |
| `path` | Path to the object. Example: `./path/file.csv` |
| `bucket_name` | The name of the bucket. Example: `my-bucket` |
| `content_type` | The MIME type of the object. Example: `text/csv` |
| `value` | The contents of the object as a data binary |

5. In the **Arguments** tab, add the object with the `bucket` property and, as a value, the name of the bucket as a string.

```json
{
  "bucket": "my-bucket"
}
```

6. Click the **Save** button.

:::note
See the [Object Storage API](/en/documentation/runtime/api-reference/storage/) reference for more details on functions available for other types of requests.
:::

Once you have the function ready, you need to create an application that will proxy the upload process for the bucket.

1. Access [Azion Console](https://console.azion.com).
2. Select the **Start with a template** option on the homepage.
3. Select the **Build from scratch** option.
4. Give your application an easy-to-remember name. Example: `my-bucket Proxy`.
5. Select the option **Run a Function**.
6. In **Choose Function**, select the function you created in the previous steps.
7. Click the **Next** button.
8. Copy the link of the application. It should be in the format `http://xxxxxxxxxx.map.azionedge.net`.
9. Run the following command in your terminal to upload an object:

```
curl -v http://xxxxxxxxxx.map.azionedge.net ./path/file.csv txt/csv --data-binary @./path/file.csv my-bucket
```

10. Run the following command in your terminal to download an object:

```
curl -v http://xxxxxxxxxx.map.azionedge.net ./path/file.csv my-bucket
```

The download of the object should occur in the folder where the requests are being executed.

---