用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/agent0ai/space-agent --skill file-download命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
Read the supplemental project documentation module
Frontend development router. Load deeper skills before editing
Use the frontend API surface correctly for app files, discovery, identity, and permission-aware browser data access.
基于 SOC 职业分类
正在显示 SKILL.md
| name | File Download |
| description | Download app files, generated blobs, or external URLs |
| metadata | {"when":{"tags":["onscreen"]}} |
Use this skill when the user asks how to let the browser download a file, whether it lives in the app filesystem, is generated at runtime, or comes from an external URL.
The server serves authenticated files directly at their layer paths. Use a URL built from location.href so the request carries the session cookie and the server enforces read permissions.
~/)/~/... maps to L2/<username>/... for the currently logged-in user.
const u = new URL(location.href);
u.pathname = '/~/BTC_ETH_ratio_chart.pdf';
const a = document.createElement('a');
a.href = u.toString();
a.download = 'BTC_ETH_ratio_chart.pdf';
a.click();
/L0/, /L1/, /L2/)Use the full layer path directly. The server checks that the authenticated user has read access before serving.
function downloadAppFile(layerPath, filename) {
// layerPath example: 'L0/_all/mod/_core/reports/template.pdf'
const u = new URL(location.href);
u.pathname = `/${layerPath}`;
const a = document.createElement('a');
a.href = u.toString();
a.download = filename;
a.click();
}
// Examples:
downloadAppFile('L0/_all/mod/_core/reports/template.pdf', 'template.pdf');
downloadAppFile('L2/alice/exports/summary.csv', 'summary.csv');
Read permissions follow the same rules as the file APIs:
L2/<username>/ own files onlyL0/<group>/ and L1/<group>/ group members onlyFor files generated on the fly, create a Blob, make an object URL, and revoke it after the click.
function downloadBlob(content, filename, mimeType = 'text/plain') {
const blob = new Blob([content], { type: mimeType });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = filename;
a.click();
URL.revokeObjectURL(url);
}
downloadBlob('hello world', 'note.txt', 'text/plain');
const csv = 'name,value\nalice,42\nbob,17';
downloadBlob(csv, 'data.csv', 'text/csv');
const json = JSON.stringify({ status: 'ok', items: [1, 2, 3] }, null, 2);
downloadBlob(json, 'result.json', 'application/json');
const bytes = new Uint8Array([0x25, 0x50, 0x44, 0x46]);
downloadBlob(bytes, , );
Fetch the remote file through the server proxy so the request is not blocked by CORS, then turn the response into a Blob download.
async function downloadExternalFile(externalUrl, filename) {
const response = await space.api.call('proxy', {
method: 'POST',
body: { url: externalUrl }
});
if (!response.ok) throw new Error(`Fetch failed: ${response.status}`);
const blob = await response.blob();
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = filename;
a.click();
URL.revokeObjectURL(url);
}
await downloadExternalFile('https://example.com/report.pdf', 'report.pdf');
If the external URL is public and CORS allows direct access from the browser, you can skip the proxy and fetch it directly with fetch(externalUrl) and the same Blob pattern.