Skip to main content

GetObjectCommand

The GetObjectCommand is used to retrieve or download an object from your DID Space. The content of the object is returned as a readable stream, making it efficient for handling files of any size without consuming excessive memory.

This is the command you'll use for any download functionality in your application.

Input

The command requires a single parameter to specify which object to retrieve.

  • key string (required) — The unique key (path and filename) of the object to be downloaded. For example, 'photos/profile.jpg' or 'documents/report.pdf'.

Output

Upon a successful request, the command returns an object with the status, headers, and the object's content as a data stream.

  • statusCode number — The HTTP status code of the response. A value of 200 indicates success.
  • statusMessage string — The HTTP status message corresponding to the status code.
  • headers RawAxiosResponseHeaders | AxiosResponseHeaders — An object containing the HTTP response headers. This can include metadata like 'content-type', 'content-length', etc.
  • data Readable — A Node.js Readable stream containing the object's data. You can pipe this stream to a file, another stream, or process its chunks directly.

Usage Example

This example demonstrates how to download an object from your DID Space and save it as a local file. It uses the pipeline function from Node.js's stream/promises module for a more concise and robust way to handle streams.

Downloading an Object with Pipeline

typescript
import { SpaceClient, GetObjectCommand } from '@blocklet/did-space-js';
import getWallet from '@blocklet/sdk/lib/wallet';
import fs from 'fs';
import path from 'path';
import { pipeline } from 'stream/promises';

// 1. Initialize the SpaceClient
const client = new SpaceClient({
  auth: {
    endpoint: 'https://www.didspaces.com/app/api/space/...',
    wallet: getWallet(),
  },
});

// 2. Define the key of the object to download and the local file path
const objectKey = 'path/to/your/file.txt';
const localFilePath = path.join(__dirname, 'downloaded_file.txt');

async function downloadObject() {
  try {
    // 3. Create and send the GetObjectCommand
    const command = new GetObjectCommand({ key: objectKey });
    const output = await client.send(command);

    // 4. Check if the request was successful
    if (output.statusCode === 200 && output.data) {
      console.log(`Successfully started downloading ${objectKey}`);

      // 5. Create a writable stream to save the file
      const writer = fs.createWriteStream(localFilePath);

      // 6. Use pipeline to efficiently transfer data and handle errors
      await pipeline(output.data, writer);

      console.log(`File downloaded successfully and saved to ${localFilePath}`);
    } else {
      // Throw an error if the download failed to be caught by the catch block
      throw new Error(`Failed to download object. Status: ${output.statusCode}, Message: ${output.statusMessage}`);
    }
  } catch (err) {
    console.error('An error occurred during the download process:', err);
  }
}

downloadObject();

Example Response (on success)

The output variable in the code above would look like this. Note that data is a stream object, not the actual file content.

Response Structure

json
{
  "statusCode": 200,
  "statusMessage": "OK",
  "headers": {
    "x-amz-id-2": "...",
    "x-amz-request-id": "...",
    "date": "Wed, 29 May 2024 08:30:00 GMT",
    "last-modified": "Tue, 28 May 2024 10:15:00 GMT",
    "etag": "\"...\"",
    "x-amz-server-side-encryption": "AES256",
    "accept-ranges": "bytes",
    "content-type": "application/octet-stream",
    "server": "SpaceServer",
    "content-length": "1024"
  },
  "data": "<ReadableStream>"
}

Best Practices

Handling Streams

The primary advantage of GetObjectCommand is its use of streaming. This is particularly important for large files, as it prevents your application from loading the entire file into memory at once. Always consume the data stream by piping it to a destination.

Error Management

For robust stream handling, we strongly recommend using the pipeline function from Node.js's stream/promises module, as shown in the example. It simplifies the code by automatically managing the data flow, handling backpressure, and propagating errors from any part of the stream chain. This eliminates the need for manual event listeners for error and finish, allowing you to use a standard try...catch block for cleaner and more reliable error management.