切换主题
🗑️ 文件删除接口
本文档介绍文件删除相关的所有接口,支持安全可控的文件删除操作。
功能概述
文件删除接口提供了安全可控的文件删除功能,支持:
- ✅ 多种删除方式(路径参数、查询参数)
- ✅ 业务类型隔离
- ✅ 删除权限控制
- ✅ 路径安全验证
- ✅ 支持多种存储类型(本地、OSS、COS、OBS、S3)
删除流程
删除方式
方式对比
| 方式 | URL格式 | 适用场景 | 推荐度 |
|---|---|---|---|
| 路径参数 | /delete/{业务类型}/{文件路径} | 标准删除,URL简洁 | ⭐⭐⭐⭐⭐ |
| 查询参数 | /delete/{业务类型}?filePath=xxx | 特殊字符路径 | ⭐⭐⭐⭐ |
| 默认删除 | /delete?filePath=xxx | 内部系统 | ⭐⭐⭐ |
接口说明
1️⃣ 路径参数删除(推荐)
通过URL路径指定业务类型和文件路径,URL更简洁直观。
接口信息
POST /delete/{业务类型}/{文件路径}1
请求参数
| 参数名 | 位置 | 类型 | 必填 | 说明 | 示例 |
|---|---|---|---|---|---|
业务类型 | Path | String | 是 | 业务类型代码 | document |
文件路径 | Path | String | 是 | 文件存储路径 | 2024/08/25/file.pdf |
请求示例
bash
curl -X POST "http://localhost:9830/delete/document/2024/08/25/23/abc123.pdf"1
javascript
// 使用fetch
async function deleteFile(businessType, filePath) {
const response = await fetch(`/delete/${businessType}/${filePath}`, {
method: 'POST'
});
const result = await response.json();
if (result.successful) {
console.log('删除成功');
} else {
console.error('删除失败:', result.msg);
}
return result;
}
// 使用示例
deleteFile('document', '2024/08/25/23/abc123.pdf');1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
javascript
// 使用axios
import axios from 'axios';
async function deleteFile(businessType, filePath) {
try {
const response = await axios.post(
`/delete/${businessType}/${filePath}`
);
if (response.data.successful) {
console.log('删除成功');
return true;
} else {
console.error('删除失败:', response.data.msg);
return false;
}
} catch (error) {
console.error('请求失败:', error);
return false;
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
响应示例
json
{
"code": 0,
"successful": true,
"msg": null
}1
2
3
4
5
2
3
4
5
json
{
"code": -1000,
"successful": false,
"msg": "该业务类型不允许删除文件"
}1
2
3
4
5
2
3
4
5
json
{
"code": -1000,
"successful": false,
"msg": "文件不存在"
}1
2
3
4
5
2
3
4
5
json
{
"code": -1000,
"successful": false,
"msg": "非法的文件路径"
}1
2
3
4
5
2
3
4
5
2️⃣ 查询参数删除
通过查询参数指定文件路径,适合路径包含特殊字符的场景。
接口信息
POST /delete/{业务类型}?filePath={文件路径}1
请求参数
| 参数名 | 位置 | 类型 | 必填 | 说明 | 示例 |
|---|---|---|---|---|---|
业务类型 | Path | String | 是 | 业务类型代码 | image |
filePath | Query | String | 是 | 文件存储路径 | /2024/08/25/photo.jpg |
请求示例
bash
curl -X POST "http://localhost:9830/delete/image?filePath=/2024/08/25/23/photo.jpg"1
javascript
async function deleteFile(businessType, filePath) {
const params = new URLSearchParams({ filePath });
const response = await fetch(`/delete/${businessType}?${params}`, {
method: 'POST'
});
return await response.json();
}
// 使用示例
deleteFile('image', '/2024/08/25/23/photo.jpg');1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
3️⃣ 默认删除接口
不区分业务类型的通用删除接口,适用于内部系统。
接口信息
POST /delete?filePath={文件路径}1
安全警告
此接口不进行业务类型校验,存在安全风险:
- ⚠️ 可能删除任意业务类型的文件
- ⚠️ 缺少业务隔离保护
- ⚠️ 建议仅在内网环境使用
- ⚠️ 生产环境必须添加额外的权限控制
请求参数
| 参数名 | 位置 | 类型 | 必填 | 说明 | 示例 |
|---|---|---|---|---|---|
filePath | Query | String | 是 | 文件存储路径 | /2024/08/25/file.pdf |
使用示例
场景1: 单文件删除
javascript
async function deleteSingleFile(businessType, filePath) {
try {
const response = await fetch(`/delete/${businessType}/${filePath}`, {
method: 'POST'
});
const result = await response.json();
if (result.successful) {
alert('文件删除成功');
// 刷新文件列表
refreshFileList();
} else {
alert(`删除失败: ${result.msg}`);
}
} catch (error) {
console.error('删除错误:', error);
alert('删除失败,请稍后重试');
}
}
// 使用示例
deleteSingleFile('document', '2024/08/25/23/report.pdf');1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
场景2: 批量删除
javascript
async function batchDelete(businessType, filePaths) {
const results = {
success: [],
failed: []
};
// 串行删除,避免并发过多
for (const filePath of filePaths) {
try {
const response = await fetch(`/delete/${businessType}/${filePath}`, {
method: 'POST'
});
const result = await response.json();
if (result.successful) {
results.success.push(filePath);
} else {
results.failed.push({ filePath, error: result.msg });
}
} catch (error) {
results.failed.push({ filePath, error: error.message });
}
// 添加延迟,避免请求过快
await new Promise(resolve => setTimeout(resolve, 100));
}
console.log(`删除完成: 成功${results.success.length}个, 失败${results.failed.length}个`);
return results;
}
// 使用示例
const files = [
'2024/08/25/23/file1.pdf',
'2024/08/25/23/file2.pdf',
'2024/08/25/23/file3.pdf'
];
batchDelete('document', files).then(results => {
if (results.failed.length > 0) {
console.error('删除失败的文件:', results.failed);
}
});1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
场景3: 带确认的删除
javascript
async function deleteWithConfirm(businessType, filePath, fileName) {
// 显示确认对话框
const confirmed = confirm(`确定要删除文件 "${fileName}" 吗?\n此操作不可恢复!`);
if (!confirmed) {
return { cancelled: true };
}
try {
const response = await fetch(`/delete/${businessType}/${filePath}`, {
method: 'POST'
});
const result = await response.json();
if (result.successful) {
alert('文件已删除');
return { success: true };
} else {
alert(`删除失败: ${result.msg}`);
return { success: false, error: result.msg };
}
} catch (error) {
console.error('删除错误:', error);
alert('删除失败,请稍后重试');
return { success: false, error: error.message };
}
}
// 使用示例
deleteWithConfirm('document', '2024/08/25/23/report.pdf', '报告.pdf');1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
场景4: Vue组件示例
vue
<template>
<div class="file-item">
<span>{{ fileName }}</span>
<button @click="handleDelete" :disabled="deleting">
{{ deleting ? '删除中...' : '删除' }}
</button>
</div>
</template>
<script>
export default {
props: {
businessType: String,
filePath: String,
fileName: String
},
data() {
return {
deleting: false
};
},
methods: {
async handleDelete() {
if (!confirm(`确定要删除 "${this.fileName}" 吗?`)) {
return;
}
this.deleting = true;
try {
const response = await fetch(
`/delete/${this.businessType}/${this.filePath}`,
{ method: 'POST' }
);
const result = await response.json();
if (result.successful) {
this.$message.success('删除成功');
this.$emit('deleted', this.filePath);
} else {
this.$message.error(`删除失败: ${result.msg}`);
}
} catch (error) {
this.$message.error('删除失败,请稍后重试');
} finally {
this.deleting = false;
}
}
}
};
</script>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
最佳实践
✅ 推荐做法
1. 权限配置
yaml
# config.yaml
files:
- business-type: document
allow-delete: true # 允许删除
- business-type: archive
allow-delete: false # 不允许删除(归档文件)1
2
3
4
5
6
7
2
3
4
5
6
7
2. 删除前确认
javascript
// ✅ 推荐:删除前确认
async function safeDelete(businessType, filePath, fileName) {
const confirmed = confirm(`确定要删除 "${fileName}" 吗?`);
if (!confirmed) return;
await deleteFile(businessType, filePath);
}
// ❌ 不推荐:直接删除
async function unsafeDelete(businessType, filePath) {
await deleteFile(businessType, filePath);
}1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
3. 错误处理
javascript
async function deleteWithErrorHandling(businessType, filePath) {
try {
const response = await fetch(`/delete/${businessType}/${filePath}`, {
method: 'POST'
});
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
}
const result = await response.json();
if (!result.successful) {
// 根据错误信息进行不同处理
if (result.msg.includes('不允许删除')) {
alert('该文件不允许删除');
} else if (result.msg.includes('不存在')) {
alert('文件不存在或已被删除');
} else {
alert(`删除失败: ${result.msg}`);
}
return false;
}
return true;
} catch (error) {
console.error('删除错误:', error);
alert('网络错误,请稍后重试');
return false;
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
4. 批量删除优化
javascript
// ✅ 推荐:控制并发数
async function batchDeleteWithConcurrency(businessType, filePaths, concurrency = 3) {
const results = [];
for (let i = 0; i < filePaths.length; i += concurrency) {
const batch = filePaths.slice(i, i + concurrency);
const batchResults = await Promise.all(
batch.map(path => deleteFile(businessType, path))
);
results.push(...batchResults);
}
return results;
}
// ❌ 不推荐:无限制并发
async function batchDeleteUncontrolled(businessType, filePaths) {
return await Promise.all(
filePaths.map(path => deleteFile(businessType, path))
);
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
⚠️ 注意事项
| 项目 | 说明 |
|---|---|
| 权限控制 | 必须在配置中设置 allow-delete: true 才能删除 |
| 路径安全 | 自动过滤 .. 和 ~ 等危险字符,防止路径遍历 |
| 删除确认 | 建议在客户端添加删除确认,防止误删 |
| 不可恢复 | 文件删除后无法恢复,请谨慎操作 |
| 批量删除 | 批量删除时建议控制并发数,避免服务器压力过大 |
| 日志记录 | 服务端会记录删除操作日志,便于审计 |
| 业务隔离 | 使用业务类型接口,确保业务数据隔离 |
🔒 安全建议
生产环境配置
yamlfiles: - business-type: important-docs allow-delete: false # 重要文档禁止删除1
2
3添加二次确认
javascriptasync function criticalDelete(businessType, filePath, fileName) { const confirm1 = confirm(`确定要删除 "${fileName}" 吗?`); if (!confirm1) return; const confirm2 = confirm('此操作不可恢复,确定继续吗?'); if (!confirm2) return; await deleteFile(businessType, filePath); }1
2
3
4
5
6
7
8
9记录删除日志
javascriptasync function deleteWithLog(businessType, filePath, operator) { // 记录删除操作 await logOperation({ action: 'delete', businessType, filePath, operator, timestamp: new Date().toISOString() }); // 执行删除 return await deleteFile(businessType, filePath); }1
2
3
4
5
6
7
8
9
10
11
12
13
响应字段说明
| 字段名 | 类型 | 说明 |
|---|---|---|
code | Number | 错误码,0表示成功 |
successful | Boolean | 操作是否成功 |
msg | String | 错误信息,成功时为null |
错误码说明
| 错误码 | 说明 | 常见原因 | 解决方案 |
|---|---|---|---|
0 | 成功 | - | - |
-1000 | 业务类型不存在 | 配置中没有该业务类型 | 检查业务类型配置 |
-1000 | 该业务类型不允许删除文件 | allow-delete: false | 修改配置或使用其他业务类型 |
-1000 | 非法的文件路径 | 路径包含 .. 或 ~ | 使用合法的文件路径 |
-1000 | 文件不存在 | 文件已被删除或路径错误 | 检查文件路径 |
-1000 | 删除失败 | 存储服务异常 | 查看服务器日志 |
常见问题
Q: 删除的文件可以恢复吗?
A: 不可以。文件删除后会从存储系统中永久删除,无法恢复。建议:
- 删除前进行二次确认
- 重要文件设置
allow-delete: false - 考虑实现软删除(标记删除而不是物理删除)
Q: 如何禁止删除某些文件?
A: 在配置文件中设置:
yaml
files:
- business-type: important
allow-delete: false # 禁止删除1
2
3
2
3
Q: 批量删除时如何提高效率?
A: 使用并发控制:
javascript
// 每次并发删除3个文件
async function batchDelete(files, concurrency = 3) {
for (let i = 0; i < files.length; i += concurrency) {
const batch = files.slice(i, i + concurrency);
await Promise.all(batch.map(f => deleteFile(f.type, f.path)));
}
}1
2
3
4
5
6
7
2
3
4
5
6
7
Q: 如何记录删除操作日志?
A: 服务端会自动记录删除日志。客户端可以在删除前后添加业务日志:
javascript
async function deleteWithLog(businessType, filePath, operator) {
console.log(`[${new Date().toISOString()}] ${operator} 删除文件: ${filePath}`);
const result = await deleteFile(businessType, filePath);
console.log(`[${new Date().toISOString()}] 删除结果:`, result);
return result;
}1
2
3
4
5
6
2
3
4
5
6
Q: 删除失败如何处理?
A: 根据错误信息进行不同处理:
javascript
async function handleDelete(businessType, filePath) {
const result = await deleteFile(businessType, filePath);
if (!result.successful) {
if (result.msg.includes('不允许删除')) {
alert('该文件受保护,不允许删除');
} else if (result.msg.includes('不存在')) {
alert('文件不存在或已被删除');
// 刷新文件列表
refreshFileList();
} else {
alert('删除失败,请稍后重试');
}
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15