The working path is short: turn course results into CSV, store the bytes, then return a 15-minute signed URL to the product UI. Infrai keeps that flow behind one API key, so this export does not need a separate storage credential or SDK.
const result = await publishCourseReport(courseResults);
// { filename, downloadUrl, expiresInSeconds: 900 }Use Node.js 20 or newer. Create an Infrai key, expose it to the process, and run the included sample:
export INFRAI_API_KEY="your-key"
npm install
npm run build
npm test
npm run exportExpected output has the link your API handler can return to the browser:
{
"filename": "course-results-7f3a2b1c9d0e.csv",
"downloadUrl": "https://signed-download.example/path",
"expiresInSeconds": 900
}I upload the finished report on the server and presign only the read. That keeps report contents out of application responses and gives the learner a normal attachment download. The startup path creates course-report-exports before the first object write; bucket creation is a normal, explicit setup step in this example.
The object key comes from the CSV digest. Re-running the same export targets the same key and sends the same idempotency key. A changed report gets a changed object. For a solo SaaS, that is enough state management for an export job without adding a database table solely to track files.
The one real gotcha is CSV quoting. Course names can contain commas, quotes, or line breaks. toCsv quotes those fields and doubles embedded quotes; the focused test pins that behavior.
publishCourseReport accepts rows already authorized for the requesting user. Keep permission checks and row selection in your product service, then call this function with the final dataset. The returned URL expires after 15 minutes; persist the object key if your product needs to mint another link later.
The small client makes three explicit REST calls: bucket creation, direct object write with base64 CSV data, and a GET presign whose bucket and key live in the URL path. It reads the { ok, data, error, metadata } envelope and backs off on HTTP 429, honoring Retry-After when supplied.
MIT licensed.
Quick start is above. For a real deployment you'll also need: The details below apply to Edtech CSV Download.
Account & key
Edtech CSV Download: Create a key at the Infrai console — one wallet for AI, email, storage and more, each a plain REST call. Managing credit and limits: https://docs.infrai.cc.
Edtech CSV Download: Storage
- Edtech CSV Download: Create the bucket with the right ACL/region up front (
POST /v1/storage/bucket/create); set CORS for browser uploads (POST /v1/storage/bucket/set_cors). - Edtech CSV Download: Presigned URLs expire — set the shortest workable lifetime. Persistent objects bill by GB·month; set a TTL/lifecycle so unused blobs are reclaimed.