文件上传

1.  接口描述

由于服务器存在超时限制,对于太大的文件,传输时间有可能会超过此限制,导致上传失败。所以对于超过20M的文件,需要不同的机制来上传。此接口专为大文件设计,上传文件的大小限制为4GB。

此接口实现超大文件上传的步骤是:

  1. 在本地把文件切割成小于10M大小的若干文件碎片,或每次上传时顺序读取本地大文件的小于10M的一部分(注意排序,碎片大小允许调整,最大不能超过20M);
  2. 多次调用此接口,按顺序把碎片依次上传。每次上传要在接收到上次上传完成服务器的成功反馈后再进行,不允许多线程传输
  3. 最后的碎片上传时,把 last 参数设为1,告知服务器上传结束;
  4. 服务器把收到的碎片文件按上传顺序进行拼接,生成一个完整的大文件,完成后把此文件的信息反馈给接口调用程序;
  5. 接收文件信息,完成。

上传文件支持的扩展名限制同普通文件上传接口。

在调用API时,在Header里要加入如下的信息

Authorization: Bearer {AccessToken}

AccessToken 的获取方式,见“认证接口”

2.  接口调用

请求URL: https://eln.iphy.ac.cn:61262/eln_api/upload
https://eln.iphy.ac.cn:61263/matelab/index.php?do=eln_api&action=upload(已废弃)
https://eln.iphy.ac.cn:61263/open_eln/eln_api_bigupload.php(已废弃)

请求方式: POST

header: content-type: multipart/form-data

POST 内容

uid 必填。系列碎片的唯一标识符,表示这一系列碎片为同一文件。对于同一系列的碎片文件,此标识必须相同,否则会导致文件不完整;不能和同时上传的其他文件冲突,否则也会导致文件损坏。长度最大45个字符;
file 必填。上传文件碎片内容,包含文件名等信息;
eln 选填。字符串。记录本名称。用户标记文件会被上传到记录本数据所在的服务器。如果调用接口的用户只有1台服务器的访问权限,则可忽略此参数;
name 选填。用于其它接口调用此文件信息时使用的名称。每个不同的文件上传,此项值都不能重复,重复会导致调用错误。注意:不是文件名。其它接口引用的格式为#file{name}。如果name为空,将使用 uid 代替。长度最大45个字符;
last 选填。默认为1。当设置为1时,表示这是最后一个文件碎片,上传结束。
hash 选填。上传文件使用sha256算法计算的hash值,用于验证服务器上文件的完整性,防止网络传输导致的文件错误。

3.  返回数据

code 错误代码;
  • 0: 成功;
  • 1: 认证 token 无效,无权限;
  • 2: 发生输入错误,错误描述见 errmsg;
  • 3: 发生服务器端错误;
  • 'refresh': 认证 Token 过期,需使用刷新Token重新获取。
id 数据库ID
name 请求时填写的name
filename 原始文件名
url 文件在服务器上的存储路径
size 文件大小
hash 文件使用 sha256 算法计算的 hash 值

示例

{
    "code": 0,
    "id": 1,
    "name": "请求时填写的name",
    "filename": "filename.zip",
    "url": "upload/eln/2022030914444.zip",
    "size": 1024,
    "hash": "5b8ebc90222960f97c48ce2984193b98dbc32e77eb5ac33c799ebb155f2e6c7a"
}

PHP 版本上传文件示例:

$url = 'https://eln.iphy.ac.cn:61262/eln_api/upload';
$data = array(
    'uid'=>'唯一标识',
    'name'=>'自定义名称',
    'eln'=>'实验记录本名称',
    'last'=>0,
    'file'=>curl_file_create('d:\filename.ext','application/octet-stream','filename.ext'),
);

$curl = curl_init();
curl_setopt_array($curl, array(
    CURLOPT_URL => $url,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_ENCODING => '',
    CURLOPT_MAXREDIRS => 10,
    CURLOPT_TIMEOUT => 0,
    CURLOPT_FOLLOWLOCATION => true,
    CURLOPT_POSTFIELDS => $data,
    CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_HTTPHEADER => array(
        "Content-Type: multipart/form-data",
    ),
));
$response = curl_exec($curl);

if($response===false)
{
    $err = curl_error($curl);
    curl_close($curl);
    die('服务器访问错误: '.$err.', url:'.$url);
}
else
{
    $info = curl_getinfo($curl);
    curl_close($curl);

    if(empty($info['http_code']))
        die('服务器未返回 HTTP 代码, url:'.$url);
    if($info['http_code']!==200)
        die('服务器访问错误, http 代码: '.$info['http_code'].',url:'.$url);
    );
}
$response_arr = json_decode($response, true);
if($response_arr == null || !isset($response_arr['errcode']))
    die('服务器信息格式错误');

echo json_encode($response_arr);

Python 版本上传文件示例:

import requests

url = "https://eln.iphy.ac.cn:61262/eln_api/upload"

payload = {'uid': '唯一标识','name': '调用名称','last': '1'}
files = [
  ('file',('文件名.txt',open('/d:/文件名.txt','rb'),'text/plain'))
]
headers = {
  'Authorization': 'Bearer token'
}

response = requests.request("POST", url, headers=headers, data=payload, files=files)

print(response.text)