使用Files API

上一节介绍了通过 URL 或 base64 直接提交图片。这种方式简单直接,但有两个限制:图片需在 48 MiB 的请求体限制内,且每次请求都要重新提交图片数据。如果需要在多个请求中复用同一张图片,或者图片较大,使用 Files API 会更合适——只需上传一次,之后通过 file_id 引用即可,推荐在以下场景使用:

Files API 目前仅支持图片格式:JPEG、PNG、GIF、WebP。格式由文件实际内容判断,而非文件名。

DeepSeek关于Files API的官方地址:

https://api-docs.deepseek.com/zh-cn/guides/files_api

基于这个API,我们完全可以设计一个文件上传、列表、删除、AI分析理解的图片管理系统。

目前 DeepSeek 的 Files API 仅支持图片格式。如果未来扩展到 PDF、Word 等文档格式(据传已在路径中),本节介绍的上传、引用、管理流程仍然适用,只需调整文件过滤器和处理逻辑即可。

上传文件

在命令窗口执行:

'''Async
Dim
imgPath As String = "C:\test\test.jpg" '本地图片文件
Dim
apiKey As String = "sk-a734b83536da45e9aedc3e42605bfb3a" '请替换为自己的密钥
Dim
hc As New HttpClient("https://api.deepseek.com/files")
hc.SkipError =
True
hc.Headers.Add(
"Authorization", "Bearer " & apiKey) '设置密钥
'
设置表单参数
hc.FormData.Add(
"purpose", "user_data")
hc.Files.Add(
"file", imgPath)
Dim
res As String = Await hc.GetDataAsync()
If
hc.StatusCode = 200 Then
    Dim jo As JObject = JsonConvert.DeserializeObject(res)
    Dim
fileid As String = jo("id") '获取文件ID
    Output.Show(jo.ToString())

Else

    MessageBoxA.Show(
"文件上传失败:" & vbCrLf & "状态码:" & hc.StatusCode & vbCrLf & "状态描述:" & hc.StatusDescription)
End
If

得到的结果类似:

{
    "id":"file-api-d3dfd5cb-1b9f-48fc-94b7-b9fe3314f401",
    "object":"file",
    "bytes":215000,
    "created_at":1791707212,
    "filename":"test.jpg",
    "purpose":"user_data"
}

其中id字段是需要记录下来的,接下来我们就可以在其他代码中通过这个id访问上传好的文件,例如:

Dim caller As New LLMCaller("https://api.deepseek.com/chat/completions", "deepseek-flash", "sk-a734b83536da45e9aedc3e42605bfb3a")
Dim
msgArray As New JArray()
'
添加用户问题
msgArray.Add(
New JObject From {
    {
"type", "text"},
    {
"text", "这张图片里有什么?"}
})

'
通过id引用我们之前上传的图片文件
msgArray.Add(
New JObject From {
    {
"type", "file"},
    {
"file_id", "file-api-d3dfd5cb-1b9f-48fc-94b7-b9fe3314f401"}
})
caller.UserMessage = msgArray

If
caller.GetResult() Then
    MessageBoxA.Show(caller.Result)

Else

    MessageBoxA.Show(caller.Error)

End
If

当然你也可以将两段代码合在一起:

'''Async
Dim
imgPath As String = "C:\test\test.jpg" '本地图片文件
Dim
apiKey As String = "sk-a734b83536da45e9aedc3e42605bfb3a" '请替换为自己的密钥
Dim
hc As New HttpClient("https://api.deepseek.com/files")
hc.SkipError =
True
hc.Headers.Add(
"Authorization", "Bearer " & apiKey) '设置密钥
'
设置表单参数
hc.FormData.Add(
"purpose", "user_data")
hc.Files.Add(
"file", imgPath)
Dim
res As String = Await hc.GetDataAsync()
If
hc.StatusCode = 200 Then
   
Dim jo As JObject = JsonConvert.DeserializeObject(res)
   
Dim fileid As String = jo("id") '获取文件ID
   
Dim caller As New LLMCaller("https://api.deepseek.com/chat/completions", "deepseek-flash", apiKey)
   
Dim msgArray As New JArray()
   
'添加用户问题
    msgArray.Add(
New JObject From {
        {
"type", "text"},
        {
"text", "这张图片里有什么?"}
    })
   
'通过id引用我们之前上传的图片文件
    msgArray.Add(
New JObject From {
        {
"type", "file"},
        {
"file_id", fileid}
    })
    caller.UserMessage = msgArray
   
If caller.GetResult() Then
            MessageBoxA.Show(caller.Result)
   
Else
            MessageBoxA.Show(caller.Error)
   
End If
Else

    MessageBoxA.Show(
"文件上传失败:" & vbCrLf & "状态码:" & hc.StatusCode & vbCrLf & "状态描述:" & hc.StatusDescription)
End
If

设置文件有效期

上传的文件默认长期有效,你可以在上传文件的时候设置一个有效期,有效期到了之后,服务器会自动删除该文件。

例如:

'''Async
Dim
imgPath As String = "C:\test\test.jpg" '本地图片文件
Dim
apiKey As String = "sk-a734b83536da45e9aedc3e42605bfb3a" '请替换为自己的密钥
Dim
hc As New HttpClient("https://api.deepseek.com/files")
hc.SkipError =
True
hc.Headers.Add(
"Authorization", "Bearer " & apiKey) '设置密钥
'
设置表单参数
hc.FormData.Add(
"purpose", "user_data")
hc.FormData.Add(
"expires_after[anchor]", "created_at") ' 锚点:创建时间
hc.FormData.Add(
"expires_after[seconds]", "604800") ' 有效期604800秒,也就是7 天
hc.Files.Add(
"file", imgPath)
Dim
res As String = Await hc.GetDataAsync()
If
hc.StatusCode = 200 Then
   
Dim jo As JObject = JsonConvert.DeserializeObject(res)
   
Dim fileid As String = jo("id") '获取文件ID
    Output.Show(jo.ToString())

Else

    MessageBoxA.Show(
"文件上传失败:" & vbCrLf & "状态码:" & hc.StatusCode & vbCrLf & "状态描述:" & hc.StatusDescription)
End
If

普通用户可以忽略接下来的内容,以下三个操作(查询指定文件、删除指定文件、查询所有文件)主要用于文件管理和清理,在常规的图片理解场景中并不需要。

查询指定文件

参考代码:

'''Async
Dim
apiKey As String = "sk-a734b83536da45e9aedc3e42605bfb3a" '请替换为自己的密钥
Dim
fileId As String = "file-api-5a55e104-0737-4478-a0f6-1990d4bf6890" '请替换为要查询的文件ID
Dim
url As String = "https://api.deepseek.com/files/" & fileId
Dim
hc As New HttpClient(url)
hc.SkipError =
True
hc.Headers.Add(
"Authorization", "Bearer " & apiKey)
Dim
res As String = Await hc.GetDataAsync()
If
hc.StatusCode = 200 Then
   
Dim file As JObject = JsonConvert.DeserializeObject(res)
   
Dim fileName As String = file("filename").ToString()
   
Dim fileBytes As Long = file("bytes").ToObject(Of Long)()
   
Dim createdAt As Long = file("created_at").ToObject(Of Long)()
   
Dim createdTime As DateTime = DateTimeOffset.FromUnixTimeSeconds(createdAt).LocalDateTime
   
Dim purpose As String = file("purpose").ToString()
   
Dim sb As New StringBuilder()
    sb.AppendLine(
"文件名:" & fileName)
    sb.AppendLine(
"文件ID:" & file("id").ToString())
    sb.AppendLine(
"大小:" & Math.Round(fileBytes / 1024, 1) & " KB")
    sb.AppendLine(
"用途:" & purpose)
    sb.AppendLine(
"上传时间:" & createdTime.ToString("yyyy-MM-dd HH:mm:ss"))
   
' 如果设置了过期时间,会返回 expires_at 字段
   
If file("expires_at") IsNot Nothing AndAlso file("expires_at").Type <> JTokenType.Null Then
       
Dim expiresAt As Long = file("expires_at").ToObject(Of Long)()
       
Dim expireTime As DateTime = DateTimeOffset.FromUnixTimeSeconds(expiresAt).LocalDateTime
        sb.AppendLine(
"过期时间:" & expireTime.ToString("yyyy-MM-dd HH:mm:ss"))
   
Else
        sb.AppendLine(
"过期时间:永久有效")
   
End If
    MessageBoxA.Show(sb.ToString())

Else

    MessageBoxA.Show(
"查询文件失败:" & vbCrLf & "状态码:" & hc.StatusCode & vbCrLf & "状态描述:" & hc.StatusDescription)
End
If

删除指定文件

参考代码:

'''Async
Dim
apiKey As String = "sk-a734b83536da45e9aedc3e42605bfb3a" '请替换为自己的密钥
Dim
fileId As String = "file-api-5a55e104-0737-4478-a0f6-1990d4bf6890" '请替换为要删除的文件ID
Dim
url As String = "https://api.deepseek.com/files/" & fileId
Dim
hc As New HttpClient(url)
hc.Method =
"DELETE" ' 明确指定请求方式为 DELETE
hc.SkipError =
True
hc.Headers.Add(
"Authorization", "Bearer " & apiKey)
Dim
res As String = Await hc.GetDataAsync()
If
hc.StatusCode = 200 Then
   
Dim jo As JObject = JsonConvert.DeserializeObject(res)
   
Dim deleted As Boolean = jo("deleted").ToObject(Of Boolean)()
   
If deleted Then
        MessageBoxA.Show(
"文件删除成功:" & vbCrLf &
           
"文件ID:" & jo("id").ToString())
   
Else
        MessageBoxA.Show(
"文件删除失败,API 返回 deleted = false。")
   
End If
Else

    MessageBoxA.Show(
"删除文件失败:" & vbCrLf & "状态码:" & hc.StatusCode & vbCrLf & "状态描述:" & hc.StatusDescription)
End
If

查询所有文件

参考代码:

'''Async
Dim
apiKey As String = "sk-a734b83536da45e9aedc3e42605bfb3a" '请替换为自己的密钥
Dim
limit As Integer = 200 ' 每页返回200个文件,1~1000,默认1000
Dim
Order As String = "desc" ' 排序方式:asc(按创建时间升序)或 desc(降序)
Dim
purpose As String = "user_data" ' 仅支持 user_data
' ---- 1.
分页获取所有文件 ----
Dim
allFiles As New JArray()
Dim
afterId As String = ""
Dim
hasMore As Boolean = True
While
hasMore
   
' 构造请求URL
   
Dim url As String = "https://api.deepseek.com/files" &
       
"?limit=" & limit &
       
"&order=" & Order &
       
"&purpose=" & purpose
   
If afterId <> "" Then
        url &=
"&after=" & afterId
   
End If
   
Dim hc As New HttpClient(url)
    hc.SkipError =
True
    hc.Headers.Add(
"Authorization", "Bearer " & apiKey)

   
Dim res As String = Await hc.GetDataAsync()
   
If hc.StatusCode <> 200 Then
        MessageBoxA.Show(
"获取文件列表失败:" & vbCrLf &
           
"状态码:" & hc.StatusCode & vbCrLf &
           
"状态描述:" & hc.StatusDescription)
       
Return ""
   
End If
   
Dim jo As JObject = JsonConvert.DeserializeObject(res)
   
Dim pageFiles As JArray = jo("data")
   
' 将当前页的文件添加到总列表
   
For Each file As JObject In pageFiles
        allFiles.Add(file)
   
Next
   
' 检查是否还有更多
    hasMore = jo(
"has_more").ToObject(Of Boolean)()
   
If hasMore Then
        afterId = jo(
"last_id").ToString()
   
End If
End
While
' ---- 2.
格式化显示所有文件信息 ----
If
allFiles.Count = 0 Then
    MessageBoxA.Show(
"没有已上传的文件。")
Else

   
Dim sb As New StringBuilder()
    sb.AppendLine(
"共 " & allFiles.Count & " 个文件:")
    sb.AppendLine()
   
For Each file As JObject In allFiles
       
Dim fileId As String = file("id").ToString()
       
Dim fileName As String = file("filename").ToString()
       
Dim fileBytes As Long = file("bytes").ToObject(Of Long)()
       
Dim createdAt As Long = file("created_at").ToObject(Of Long)()
       
Dim createdTime As DateTime = DateTimeOffset.FromUnixTimeSeconds(createdAt).LocalDateTime
        sb.AppendLine(
"文件名:" & fileName)
        sb.AppendLine(
"  文件ID:" & fileId)
        sb.AppendLine(
"  大小:" & Math.Round(fileBytes / 1024, 1) & " KB")
        sb.AppendLine(
"  上传时间:" & createdTime.ToString("yyyy-MM-dd HH:mm:ss"))

       
' 如果设置了过期时间,会返回 expires_at 字段
       
If file("expires_at") IsNot Nothing AndAlso file("expires_at").Type <> JTokenType.Null Then
           
Dim expiresAt As Long = file("expires_at").ToObject(Of Long)()
           
Dim expireTime As DateTime = DateTimeOffset.FromUnixTimeSeconds(expiresAt).LocalDateTime
            sb.AppendLine(
"  过期时间:" & expireTime.ToString("yyyy-MM-dd HH:mm:ss"))
       
Else
            sb.AppendLine(
"  过期时间:永久有效")
       
End If
        sb.AppendLine()
   
Next
    Output.Show(sb.ToString())

End
If


本页地址:http://www.foxtable.com/webhelp/topics/7225.htm