方法调用追溯
首先web请求查看上传api在哪
http://127.0.0.1:5001/console/api/files/upload?source=datasets
然后搜索files/upload(在dify中,接口一般是通过蓝图进行注册的)并且一步步追溯,找到最终的存储位置
这里我们发现其实存储类中已经有实现了相应的下载接口,但是他不返回,只是将文件下载到指定目录了,所以不能使用
真正的文件下载应该是load部分,加载文件内容并返回
一步步向上追溯,最终找到调用入口
其实这个方法就实现了文件下载的方法,我们只需要稍加调整就可以使用了
测试代码
最终测试代码如下,如果不加quoted_filename的话可能会报错编码格式错误:
dify本地部署部分代码
class FilePreviewApi(Resource):
@setup_required
@login_required
@account_initialization_required
def get(self, file_id):
file_id = str(file_id)
# text = FileService.get_file_preview(file_id)
# return {"content": text}
generator, upload_file = FileService.get_file_generator_by_file_id(file_id, "", "", "")
response = Response(
generator,
mimetype=upload_file.mime_type,
direct_passthrough=True,
headers={},
)
if upload_file.size > 0:
response.headers["Content-Length"] = str(upload_file.size)
quoted_filename = quote(upload_file.name) # URL 编码为 UTF-8
response.headers[
"Content-Disposition"] = f"attachment; filename*=UTF-8''{quoted_filename}"
return response
js前端测试代码(直接保存为html文件即可使用)
<!DOCTYPE html>
<html>
<head>
<title>Download File</title>
</head>
<body>
<button onclick="downloadFile()">下载文件</button>
<script>
async function downloadFile() {
try {
const response = await fetch('http://127.0.0.1:5001/console/api/files/3d313bcc-f36e-4b90-8c8f-88ed05898b1c/preview', {
method: 'GET',
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36',
'Authorization': 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoiN2E5YWRhZWYtNzQ0Ni00ZmRjLTkxMzktYzIyYzg3ZjRhZmY5IiwiZXhwIjoxNzQ3OTA3OTE2LCJpc3MiOiJTRUxGX0hPU1RFRCIsInN1YiI6IkNvbnNvbGUgQVBJIFBhc3Nwb3J0In0.bBLKl17erEnuBPYxr0SmeqwGCpeSK3Kg3rnSp9fRxzw',
'Accept': '*/*'
}
});
if (!response.ok) {
throw new Error("下载失败:" + response.status);
}
const blob = await response.blob();
const url = window.URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'downloaded_file'; // 可以根据响应 header 提取文件名
document.body.appendChild(a);
a.click();
a.remove();
window.URL.revokeObjectURL(url);
} catch (error) {
console.error("下载错误:", error);
}
}
</script>
</body>
</html>
文件下载接口
根据测试代码的内容我们已经确定好核心逻辑了,后续根据项目需要重新命名一个download-file的接口即可