文件管理服务 JFile

简介

文件管理服务 JFile 基于公有云的对象存储,提供海量、安全、高可靠和低成本的云存储服务。用户可以通过 JFile 上传文件,并且上传的文件可以在其它任意 Jarvis 系统中被使用。JFile 完成应用和公有云存储之前的转发,后续提供简单的云文件管理功能。

相比传统的文件存储,JFile 有以下优点:

  • 易用性,支持 RESTful API 和多版本 SDK 等方式接入;

  • 高可靠,实现文件多节点备份,文件持久性不低于 99.999999999%;

  • 低成本,相比自建存储降低 25%-75% 的成本,且存储容量无限制;

  • 速度快,基于公有云存储,提供 CDN 下载链接,使文件传输更快、更稳定;

应用场景

图片和音视频等应用的海量存储

JFile 可用于图片、音视频、日志、excel、word 等海量文件的存储。 各种终端设备、web 网站程序、移动应用可以直接向 JFile 写入或读取数据。并且提供安全的文件加密方式,特别适合云上应用接入。

应用案例

常见问题

文件流

上传的文件以文件流的形式上传。

文件名

如果需要文件名不变,设置 random_name = 0。random_name = 1 生成随机文件名。

重名文件

每个用户都有自己的存储空间,用户只可以上传到自己的存储空间中,不会与其他用户的文件冲突。

如果上传时设置了 random_name = 0,保存时按照用户上传的文件名进行保存,当再次上传相同文件名的文件时则默认会覆盖原有的文件,每次覆盖之后返回的 file_token 都相同;可以设置 overwrite=0 来禁止 Jarvis File 覆盖已存在的文件,如果发生文件重名则会返回 400 错误。

自定义 file_token

在上传时可以指定自定义的 filetoken(customfiletoken),用户可以使用该自定义的 filetoken 进行下载和删除。

当下载其他用户自定义的 filetoken 时必须指定对方的 apptoken (belongapptoken),否则只会下载自己自定义的 file_token。

自定义 filetoken 只是一个别名,实际上传后 Jarvis File 还会返回真实的 filetoken,同样可以使用返回的 filetoken 进行下载和删除,请尽量避免使用 Jarvis File 的 filetoken 命名规则,否则可能会造成 file_token 冲突而导致文件不能被下载。

版本控制

Jarvis File 采用 API 路由中传递版本号(例如:/file/v6/files 或 /file/v6/files),调用不同的 Jarvis File 的版本实现不同的上传/下载方式,调用不同版本的 Jarvis File 上传都不会改变文件的存储方式,请放心使用任意版本进行下载。

文件安全性

有两种方式保证文件安全:

  • 设置文件有效期,private = “1”,为私有文件,默认有效期 600s

  • 通过设置将文件加密,encryption = “1”

帮助

Jarvis File 提供了测试/生产环境的测试页面( http://jua.huifutest.com/file/v6/web/index.html, https://jua.cloudpnr.com/file/v6/web/index.html) 可以方便的文件上传/下载/删除,同时也可以使用该测试页面获取和设置共享用户。

使用测试页面需要注意尽量避免使用低版本的浏览器或 IE 浏览器,测试页面提交的 apptoken 及 appkey 存储于浏览器的缓存中,请及时清理缓存以免泄漏 app_key。

白名单

Jarvis File 对不同安全级别的文件采用了不同的方式对文件进行存储,会导致在文件下载时返回不固定的域名。 默认返回外网地址,请确保以下外网地址设置成白名单:

API 文档

账号申请(app_token、app_key)

账号申请流程,即 BUser 申请,请见章节 “BUser申请流程

请求地址

测试地址:http://jua.huifutest.com

生产外网地址:https://jua.cloudpnr.com

生产内网地址:http://jua.hfinside.com

公共参数

公共请求参数

除了下载密码保护文件接口,其它接口都有以下请求参数

名称

类型

是否必须

限制

描述

app_token

String

应用 app_token

signature

String

signature 注:明文拼接规则第2条除外,请求地址不参与明文拼接,具体生成方式请参考”API签名

参数校验错误返回码


返回码 返回信息


30013 param exist empty - 参数为空

30014 param type error - 参数类型错误

30015 param length error - 参数长度错误


上传文件

使用 JFile 上传的文件存储在云端后,会自动将文件复制到多个不同的节点进行存储,确保文件不会丢失。

根据使用用途文件分为 3种 文件:

  1. 公共文件,上传的文件可以在任何时间任何地点下载,并且对文件提供了 cdn 加速服务。设置参数 private = “0”;

  2. 普通的私有文件,文件下载地址有效期,默认有效期 600s;

  3. 加密的私有文件,上传的文件由系统加密机进行加密存储,保证文件的安全性。设置参数 encryption = “1”;

HTTP Request

POST http://jua.huifutest.com/file/v6/files

请求参数

名称

类型

是否必须

限制

描述

files

文件

上传的文件

timestamp

String

10 位或 13 位,两次提交不能重复

时间戳

encryption

String

“1” 或 “0”,默认为 “0”

是否加密存储,”1” 表示文件加密存储 ,”0” 表示文件不加密存储

is_cdn

String

“1” 或 “0”,默认为 “0”

是否开启CDN加速,”1” 表示开启 ,”0” 表示不开启。需频繁下载的资源文件建议开启,开启后可避免产生较大的费用(private 必须为0,否则不生效)

private

String

“1” 或 “0”,默认为 “1”

是否是私有文件,”1” 表示私有文件,下载地址有有效期限制(有效期默认值600s) ,”0”表示公有文件,下载地址无有效期限制 ,注:公有文件无需加密

path

String

小于等于 200 个字节

保存的路径

random_name

String

“1” 或 “0”,默认值为 “1”

文件名是否随机 ,”1” 表示文件上传后文件名随机 ,”0”表示文件上传后文件名不变,相同的文件名会覆盖原有的文件

over_write

String

“1” 或 “0”,默认值为 “1”

当random_name 为 “0” 时传递该参数表示是否覆盖文件 ,”1”表示强制覆盖已存在的文件,”0” 表示不覆盖(当出现重名文件时会返回 400错误)

inside_job

String

“1” 或 “0”,默认值为 “0”

是否内网用户 ,”1” 表示内网用户,”0” 表示非内网用户,内网用户则会返回*.hfinside.com 内网地址,否则会返回 *.cloudpnr.com 公网地址

custom_file_token

String

小于等于 24 个字节

自定义 file_token 如果指定的话可以使用自定义的 file_token 进行下载和删除

响应参数

名称

类型

描述

file_token

String

上传的文件 ID

download_url

String

文件下载地址(如果是私有文件,文件下载地址使用默认的有效期 600s)

失败响应

会返回 4xx5xx,并在响应体中提供一段 JSON 格式的详细错误信息,通用的错误可以参考错误代码章节,使用下表可以查询到 上次文件 API 的错误码。


返回码 返回信息


20203 upload file is too large -上传文件大小超限

30002 sign error - 验签失败,接口 sign 与后台计算结果不一致

30003 save file error -上传文件时,Jarvis 无法保存文件

30006 upload file extension illegal -传递了 Jarvis 不支持的文件扩展名

30007 upload error - 上传文件失败

30008 write file info error -文件信息写库失败,状态码 500

30012 param files is none - 参数 files 为空

30016 param contain special character -文件名包含非法字符

30017 timestamp error - 参数时间戳不为 10 位数字

30019 incorrect signature -签名验签失败

30020 password incorrect - 密码错误

30022 path name illegal -路径名称非法,路径中不能含有特殊 字符

30023 repeated timestamp -相同用户的时间戳重复

30024 unable upload public file with password

-不可以上传带密码的公共文件

30025 random_name must be 1 or 0 -“随机名称” 参数必须是 1 或 0

30026 private must be 1 or 0 -“私有文件” 参数必须是 1 或 0


调用示例

# 创建需要上传的文件
echo 'hello world!' > /tmp/test.txt
curl -X POST \
     -F "files=@/tmp/test.txt" \
     -F "password=1234567890" \
     -F "app_token=app-a8187ae7-5671-4888-4321-2cc8c4d476ba" \
     -F "path=/dir1/" \
     -F "signature=ce879cded4867fe35d8afa7a08a40e5ac3f8fd80a93da717e9048b2c99840f80" \
     http://jua.huifutest.com/file/v6/files

python

import requests

# 创建需要上传的文件
file = open('/tmp/test.txt', 'w')
file.write('hello world!')
file.close()

url = "http://jua.huifutest.com/file/v6/files" # 测试服务器
app_token = "app-a8187ae7-5671-4888-4321-2cc8c4d476ba"
file_info = {
  'app_token': app_token,
  'password': password,
  'path': '/dir1/',
  'timestamp': str(int(time.time())),
  'private': is_private,
  'random_name': is_random_name
} # 拼接请求参数

# 根据参数 key 的值 顺序拼接其 key=value& , 实际做代码操作时, 可以使用排序方法拼接更为合适, 以下只做例子展示
files = open('../test_file/test.txt', 'rb')
encrypt_dict = {
  'app_token': file_info['app_token'],
  'timestamp': file_info['timestamp'],
  'files': md5(files),
  'password': file_info['password'],
  'path': file_info['path'],
  'private': file_info['private'],
  'random_name': file_info['random_name']
}
keys = encrypt_dict.keys()
keys = sorted(keys, reverse=False)
# 拼接 key 和 value 值
values = ''
for key in keys:
    value = str(encrypt_dict.get(key))
    if len(value) == 0:
      continue
    values = values + '&' + str(key) + '=' + value
plain_text = 'POST' + values[1:]
# 对拼接好的字符串, 以 app_key 作为秘钥进行 hmacsha256 加密处理
file_info['signature'] = hmacsha256(plain_text, app_key)

# 上传文件
response = requests.post(url,
                         files={'files': files},
                         data=file_info) # 发送请求
print(response.status_code) # 打印状态码
print(response.text) # 打印返回内容

java

建议,引入 status-file,具体请参考”JAVA-SDK说明

成功响应

200
{
  "file_token": "20f1ee3a-2430-11e7-8e4f-525400792f1a",
  "download_url": "......"
}

失败响应

400
{
  "message": "incorrect signature",
  "return_code": 30019
}

获取文件

返回指定 file_token 的文件下载地址或文件内容。

HTTP Request

GET http://jua.huifutest.com/file/v6/files

请求参数

名称

类型

是否必须

限制

描述

file_token

String

文件 ID

expires

String

有效期 ( 秒 ),默认 600 秒

inside_job

String

“1” 或 “0”,默认值为 “0”

是否内网用户 ,”1” 表示内网用户,”0” 表示非内网用户,内网用户则会返回*.hfinside.com 内网文件下载地址,否则会返回 *.cloudpnr.com 公网文件下载地址

is_cdn

String

“1” 或 “0”,默认为 “0”

是否开启CDN加速,”1” 表示开启 ,”0” 表示不开启,需频繁下载的资源文件建议开启,开启后可避免产生较大的费用

belong_app_token

String

当下载其他用户的自定义 file_token 时需要指定对方的 app_token 否则只会下载自己的自定义 file_token 文件

return_json

String

“1” 或 “0”,默认值为 “0”

接口返回是 json 格式还是实际文件的 302 跳转链接,该参数多用于 js 库中用来只获取文件的下载地址

响应参数

有三种响应参数:

  1. 如果 return_json = “1” 时,则返回 json 格式,json 内容请参阅下表;

  2. 如果 API 请求参数设置成重定向,HTTP 返回码 200,返回 body 为文件内容;

  3. 如果 API 请求参数设置成非重定向,HTTP 返回码 302,返回 header 头 Location 参数为文件下载地址;

注:如果上传文件时指定了密码,则只能通过上述第 2 条获取文件下载地址,然后通过 “下载密码保护文件” 接口获取文件内容


名称 类型 描述


file_name String 上传时的文件名称。 file_suffix String

上传时的文件后缀名。 file_url String 文件下载地址(如果是私有文件,文件下载地址使用默认的有效期 600s)

失败响应

会返回 4xx5xx,并在响应体中提供一段 JSON 格式的详细错误信息,通用的错误可以参考错误代码章节,使用下表可以查询到 获取下载地址 API 的错误码。


返回码 返回信息


20202 download file fail - 获取文件下载链接失败,状态码 500

30002 sign error - 验签失败,接口 signature 与后台计算结果不一致

30004 app token not exist - app_token 不存在

30009 query file info error - 下载文件时查询文件信息读库失败, 状态码

500

30010 download file error - 获取下载文件链接失败,状态码 500

30011 file token not exist - 下载文件时,传递的

file_token,对应的文件不存在,状态码 404

30019 incorrect signature - 签名验签失败


shell

curl "https://jfile.cloudpnr.com/file/v6/files?app_token=app-66a4740a-deef-42e5-85b0-089cf86de1ef&expires=600&file_token=54a3ba55-9967-3f71-b4cf-2610ce43caa6&signature=efa4048aee10a0f2ceab6540368a141eee6f28c28ffac9dafda218c415482f27"

python

import requests

url = "http://jua.huifutest.com/file/v6/files" # v6 测试服务器

# 拼接请求参数
file_info = {
  'file_token': file_token,
  'app_token': app_token,
  'expires': '600'
}

# 根据参数 key 的值 顺序拼接其 key=value& , 实际做代码操作时, 可以使用排序方法拼接更为合适, 以下只做例子展示
encrypt_dict = {
  'app_token': file_info['app_token'],
  'file_token': file_info['file_token'],
  'expires': file_info['expires']
}
keys = encrypt_dict.keys()
keys = sorted(keys, reverse=False)
# 拼接 key 和 value 值
values = ''
for key in keys:
    value = str(encrypt_dict.get(key))
    if len(value) == 0:
      continue
    values = values + '&' + str(key) + '=' + value
plain_text = 'POST' + values[1:]
# 对拼接好的字符串, 以 app_key 作为秘钥进行 hmacsha256 加密处理
file_info['signature'] = hmacsha256(plain_text, app_key)

# 获取文件的下载地址
response = requests.get(url, params=file_info)
print(response.status_code) # 打印状态码
print(response.text) # 打印返回内容

java

建议,引入 status-file,具体请参考”JAVA-SDK说明

成功响应

200
{
  "file_name": "test.txt",
  "file_suffix": "txt",
  "file_url": "http://jfile.cloudpnr.com/8ed14c50-a344-11e7-bf68-005056c00008.jpeg?Signature=bTbWQiXztuiDXmr1JuOw6MYfPmY%3D&OSSAccessKeyId=LTAIazOFLTVB223123mUh9&Expires=15065231266708"
}

失败响应

400
{
  "message": "incorrect signature",
  "return_code": 30019
}

删除文件

删除指定 file_token 的文件。

HTTP Request

DELETE http://jua.huifutest.com/file/v6/files

请求参数

名称

类型

是否必须

限制

描述

file_token

String

文件 ID

password

String

如果上传的文件有密码,需提供密码

响应参数

返回 200 状态码表示删除成功。

失败响应

会返回 4xx5xx,并在响应体中提供一段 JSON 格式的详细错误信息,通用的错误可以参考错误代码章节,使用下表可以查询到 删除文件 API 的错误码。


返回码 返回信息


30002 sign error - 验签失败,接口 signature 与后台计算结果不一致

30004 app token not exist - app_token 不存在

30011 file token not exist - 删除文件时,传递的 file_token

对应的文件不存在,状态码 404

30019 incorrect signature - 签名验签失败

30020 password incorrect - 密码与上传的不匹配

30021 delete file error - 删除文件失败,无法删除远端文件


shell

curl -X DELETE \
     -F "files=@/tmp/test.txt" \
     -F "password=1234567890" \
     -F "app_token=app-a8187ae7-5671-4888-4321-2cc8c4d476ba" \
     -F "file_token=4b37df98-259e-11e7-a963-f45c898f6be5" \
     -F "signature=ce879cded4867fe35d8afa7a08a40e5ac3f8fd80a93da717e9048b2c99840f80" \
     http://jua.huifutest.com/file/v6/files

python

import requests

url = "http://jua.huifutest.com/file/v6/files" # 测试服务器

# 拼接请求参数
file_info = {
  'file_token': file_token,
  'app_token': app_token,
  'password': password
}

# 根据参数 key 的值 顺序拼接其 value , 实际做代码操作时, 可以使用排序方法拼接更为合适, 以下只做例子展示
encrypt_dict = {
  'app_token': file_info['app_token'],
  'file_token': file_info['file_token'],
  'password': file_info['password']
}
keys = encrypt_dict.keys()
keys = sorted(keys, reverse=False)
# 拼接 key 和 value 值
values = ''
for key in keys:
    value = str(encrypt_dict.get(key))
    if len(value) == 0:
      continue
    values = values + '&' + str(key) + '=' + value
plain_text = 'POST' + values[1:]
# 对拼接好的字符串, 以 app_key 作为秘钥进行 hmacsha256 加密处理
file_info['signature'] = hmacsha256(plain_text, app_key)

# 删除文件
response = requests.delete(url, data=file_info)
print(response.status_code) # 打印状态码
print(response.text) # 打印返回内容

java

建议,引入 status-file,具体请参考”JAVA-SDK说明

成功响应

200

失败响应

404

下载密码保护文件

临时下载链接和连接的有效期由接口获取下载地址生成,有效期内输入密码即可下载。

HTTP Request

GET http://jua.huifutest.com/file/v6/download

请求参数

head 中添加密码

  • 使用浏览器时,输入临时下载地址会弹出授权对话框,在对话框中输入文件的密码即可

  • 通过 API 调用时,将密码添加在 HTTP 请求头的 Authorization 字段,Authorization 的计算方式:base64encode(":"+password)

    例如:

    GET /file/v6/download?xxxxx=xxxxxx HTTP/1.1 Host: http://jua.huifutest.com Authorization: Basic amZfdGVzdDpqZl8yOTFYRUZWUEJG

响应参数


名称 类型 描述


(body) 二进制流 文件的内容


调用成功后,将文件二进制流返回,并修改响应体中文件的原始文件名。

失败响应

会返回 4xx5xx,并在响应体中提供一段 JSON 格式的详细错误信息,通用的错误可以参考错误代码章节,使用下表可以查询到 获取密码保护文件 API 的错误码。


返回码 返回信息


20202 download file fail - 下载文件出错,状态码 400 或 500

20207 file expired - 临时文件有效期超时,状态码 400

30001 params exception - 获取参数失败,状态码 400

30011 file token not exist - 文件ID不存在,状态码 400


共享文件

jarvis 用户可以将自己的某一个目录下的 file_token 共享给其他 jarvis 用户下载,被共享的 jarvis 用户只能下载到上传方指定共享目录下的文件。

获取所有共享的路径

HTTP Request

GET http://jua.huifutest.com/file/v6/share

请求参数

名称

类型

是否必须

限制

描述

page_number

Int

当前页码,默认为 “1”

page_count

Int

分页条数,默认为 “10”

响应参数

名称

类型

描述

total_page

String

总页数

current_page

String

当前页

path_list

Array

共享路径列表

path_list:

名称

类型

描述

file_path

String

共享文件夹路径

guest_count

String

共享给其它 app_token的个数

获取指定路径的共享用户列表

HTTP Request

GET http://jua.huifutest.com/file/v6/share/guest

请求参数

名称

类型

是否必须

限制

描述

file_path

String

共享文件夹路径

page_number

Int

当前页码,默认为 “1”

page_count

Int

分页条数,默认为 “10”

响应参数

名称

类型

描述

total_page

String

总页数

current_page

String

当前页

guest_info

Array

共享给其它 app_token的列表

guest_info:

名称

类型

描述

guest_app_token

String

访客的 app_token

insert_time

String

加入共享的时间

添加共享用户

HTTP Request

POST http://jua.huifutest.com/file/v6/share/guest

请求参数

名称

类型

是否必须

限制

描述

file_path

String

共享文件夹路径

guest_app_token

Int

访客的 app_token

app_token

Int

app_token

响应参数

API 调用成功后会返回 200,其他返回码请见通用返回码

删除共享用户

HTTP Request

DELETE http://jua.huifutest.com/file/v6/share/guest

请求参数

名称

类型

是否必须

限制

描述

file_path

String

共享文件夹路径

guest_app_token

Int

访客的 app_token

app_token

Int

app_token

响应参数

API 调用成功后会返回 200,其他返回码请见通用返回码

SDK 说明

SDK 介绍

为了方便客户端上传和下载文件,提供以下 SDK。

Python SDK

提供文件上传、下载和删除的 Python 原生 SDK;

下载地址

Java SDK

提供文件上传、下载和删除的 Java SDK。

通过 pom 依赖中 添加 saturn-file 可参考:”status-file接入指南

saturn-file

1)引入依赖

pom.xml文件加入以下依赖:

<dependency>
    <groupId>com.huifu.saturn</groupId>
    <artifactId>saturn-file</artifactId>
    <version>1.0.6.8</version>
</dependency>

2)使用说明

请见:”status-file说明

iOS SDK

提供文件上传、下载和删除的 iOS 原生 SDK;

下载地址