今年国庆假期终于可以憋在家里了不用出门了,不用出去看后脑了,真的是一种享受。这么好的光阴怎么浪费,睡觉、吃饭、打豆豆这怎么可能(耍多了也烦),完全不符合我们程序员的作风,赶紧起来把文章写完。
这篇文章比较基础,在国庆期间的业余时间写的,这几天又完善了下,力求把更多的前端所涉及到的关于文件上传的各种场景和应用都涵盖了,若有疏漏和问题还请留言斧正和补充。
以下是本文所涉及到的知识点,break or continue ?
原理很简单,就是根据 http 协议的规范和定义,完成请求消息体的封装和消息体的解析,然后将二进制内容保存到文件。
我们都知道如果要上传一个文件,需要把 form 标签的enctype设置为multipart/form-data,同时method必须为post方法。
那么multipart/form-data表示什么呢?
multipart互联网上的混合资源,就是资源由多种元素组成,form-data表示可以使用HTML Forms 和 POST 方法上传文件,具体的定义可以参考RFC 7578。
multipart/form-data 结构
看下 http 请求的消息体
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryDCntfiXcSkPhS4PN 表示本次请求要上传文件,其中boundary表示分隔符,如果要上传多个表单项,就要使用boundary分割,每个表单项由———XXX开始,以———XXX结尾。
每一个表单项又由Content-Type和Content-Disposition组成。
Content-Disposition: form-data 为固定值,表示一个表单元素,name 表示表单元素的 名称,回车换行后面就是name的值,如果是上传文件就是文件的二进制内容。
Content-Type:表示当前的内容的 MIME 类型,是图片还是文本还是二进制数据。
解析
客户端发送请求到服务器后,服务器会收到请求的消息体,然后对消息体进行解析,解析出哪是普通表单哪些是附件。
可能大家马上能想到通过正则或者字符串处理分割出内容,不过这样是行不通的,二进制buffer转化为string,对字符串进行截取后,其索引和字符串是不一致的,所以结果就不会正确,除非上传的就是字符串。
不过一般情况下不需要自行解析,目前已经有很成熟的三方库可以使用。
至于如何解析,这个也会占用很大篇幅,后面的文章在详细说。
使用 form 表单上传文件
在 ie时代,如果实现一个无刷新的文件上传那可是费老劲了,大部分都是用 iframe 来实现局部刷新或者使用 flash 插件来搞定,在那个时代 ie 就是最好用的浏览器(别无选择)。
DEMO
这种方式上传文件,不需要 js ,而且没有兼容问题,所有浏览器都支持,就是体验很差,导致页面刷新,页面其他数据丢失。
HTML
<form method="post" action="http://localhost:8100" enctype="multipart/form-data">
选择文件:
<input type="file" name="f1"/> input 必须设置 name 属性,否则数据无法发送<br/>
<br/>
标题:<input type="text" name="title"/><br/><br/><br/>
<button type="submit" id="btn-0">上 传</button>
</form>
复制代码
服务端文件的保存基于现有的库koa-body结合 koa2实现服务端文件的保存和数据的返回。
在项目开发中,文件上传本身和业务无关,代码基本上都可通用。
在这里我们使用koa-body库来实现解析和文件的保存。
koa-body 会自动保存文件到系统临时目录下,也可以指定保存的文件路径。
然后在后续中间件内得到已保存的文件的信息,再做二次处理。
NODE
/**
* 服务入口
*/
var http = require('http');
var koaStatic = require('koa-static');
var path = require('path');
var koaBody = require('koa-body');//文件保存库
var fs = require('fs');
var Koa = require('koa2');
var app = new Koa();
var port = process.env.PORT || '8100';
var uploadHost= `http://localhost:${port}/uploads/`;
app.use(koaBody({
formidable: {
//设置文件的默认保存目录,不设置则保存在系统临时目录下 os
uploadDir: path.resolve(__dirname, '../static/uploads')
},
multipart: true // 开启文件上传,默认是关闭
}));
//开启静态文件访问
app.use(koaStatic(
path.resolve(__dirname, '../static')
));
//文件二次处理,修改名称
app.use((ctx) => {
var file = ctx.request.files.f1;//得道文件对象
var path = file.path;
var fname = file.name;//原文件名称
var nextPath = path+fname;
if(file.size>0 && path){
//得到扩展名
var extArr = fname.split('.');
var ext = extArr[extArr.length-1];
var nextPath = path+'.'+ext;
//重命名文件
fs.renameSync(path, nextPath);
}
//以 json 形式输出上传文件地址
ctx.body = `{
"fileUrl":"${uploadHost}${nextPath.slice(nextPath.lastIndexOf('/')+1)}"
}`;
});
/**
* http server
*/
var server = http.createServer(app.callback());
server.listen(port);
console.log('demo1 server start ...... ');
复制代码
CODE
https://github.com/Bigerfe/fe-learn-code/
要使用的是wkhtmltopdf的Python封装——pdfkit
安装
1. Install python-pdfkit:
$ pip install pdfkit
2. Install wkhtmltopdf:
$ sudo apt-get install wkhtmltopdf
sudo yum intsall wkhtmltopdf
brew install Caskroom/cask/wkhtmltopdf
使用
一个简单的例子:
import pdfkit
pdfkit.from_url('http://google.com', 'out.pdf')
pdfkit.from_file('test.html', 'out.pdf')
pdfkit.from_string('Hello!', 'out.pdf')
你也可以传递一个url或者文件名列表:
pdfkit.from_url(['google.com', 'yandex.ru', 'engadget.com'], 'out.pdf')
pdfkit.from_file(['file1.html', 'file2.html'], 'out.pdf')
也可以传递一个打开的文件:
with open('file.html') as f:
pdfkit.from_file(f, 'out.pdf')
如果你想对生成的PDF作进一步处理, 你可以将其读取到一个变量中:
# 设置输出文件为False,将结果赋给一个变量
pdf = pdfkit.from_url('http://google.com', False)
你可以制定所有的 wkhtmltopdf 选项 http://wkhtmltopdf.org/usage/wkhtmltopdf.txt. 你可以移除选项名字前面的 '--' .如果选项没有值, 使用None, False or * 作为字典值:
options = {
'page-size': 'Letter',
'margin-top': '0.75in',
'margin-right': '0.75in',
'margin-bottom': '0.75in',
'margin-left': '0.75in',
'encoding': "UTF-8",
'no-outline': None
}
pdfkit.from_url('http://google.com', 'out.pdf', options=options)
默认情况下, PDFKit 将会显示所有的 wkhtmltopdf 输出. 如果你不想看到这些信息,你需要传递一个 quiet 选项:
options = {
'quiet': ''
}
pdfkit.from_url('google.com', 'out.pdf', options=options)
由于wkhtmltopdf的命令语法 , TOC 和 Cover 选项必须分开指定:
toc = {
'xsl-style-sheet': 'toc.xsl'
}
cover = 'cover.html'
pdfkit.from_file('file.html', options=options, toc=toc, cover=cover)
当你转换文件、或字符串的时候,你可以通过css选项指定扩展的 CSS 文件。
# 单个 CSS 文件
css = 'example.css'
pdfkit.from_file('file.html', options=options, css=css)
# Multiple CSS files
css = ['example.css', 'example2.css']
pdfkit.from_file('file.html', options=options, css=css)
你也可以通过你的HTML中的meta tags传递任意选项:
body = """
<html>
<head>
<meta name="pdfkit-page-size" content="Legal"/>
<meta name="pdfkit-orientation" content="Landscape"/>
</head>
Hello World!
</html>
"""
pdfkit.from_string(body, 'out.pdf') #with --page-size=Legal and --orientation=Landscape
配置
每个API调用都有一个可选的参数。这应该是pdfkit.configuration()API 调用的一个实例. 采用configuration 选项作为初始化参数。可用的选项有:
示例 :针对wkhtmltopdf不在系统路径中(不在$PATH里面)
PATH里面):
config = pdfkit.configuration(wkhtmltopdf='/opt/bin/wkhtmltopdf'))
pdfkit.from_string(html_string, output_file, configuration=config)
问题
IOError:'No wkhtmltopdf executable found':
确保 wkhtmltopdf 在你的系统路径中(PATH), 会通过 configuration进行了配置 (详情看上文描述)。 在Windows系统中使用where wkhtmltopdf命令 或 在 linux系统中使用 which wkhtmltopdf 会返回 wkhtmltopdf二进制可执行文件所在的确切位置.
如果出现这个错误意味着 PDFKit不能处理一个输入。你可以尝试直接在错误信息后面直接运行一个命令来查看是什么导致了这个错误 (某些版本的 wkhtmltopdf会因为段错误导致处理失败)
确保两项:
1)、你的系统中有中文字体
2)、在html中加入
下面是我随便写的一个HTML表格:
<html>
<head><meta charset="UTF-8"></head>
<body>
<table width="400" border="1">
<tr>
<th align="left">Item....</th>
<th align="right">1</th>
</tr>
<tr>
<td align="left">衣服</td>
<td align="right">1.10</td>
</tr>
<tr>
<td align="left">化妆品</td>
<td align="right">.00</td>
</tr>
<tr>
<td align="left">食物</td>
<td align="right">0.40</td>
</tr>
<tr>
<th align="left">tOTAL</th>
<th align="right">01.50</th>
</tr>
</table>
</body>
</html>
下面是生成的PDF截图
者:时蓬,王琴,白青江,范全林
中国科学院国家空间科学中心
空间科学与深空探测规划论证中心
21世纪第三个十年开启之际,中国嫦娥任务成为月球探测的亮点。
嫦娥四号2019年1月3日实现国际首次月背软着陆以来,着陆器和“玉兔二号”月球车分别于2020年11月10日和11月9日结束月夜休眠,迎来第24月昼[1]。
今天上午(12月16日)9时15分,嫦娥五号轨道器和返回器组合体上两台25N发动机工作约8秒钟,顺利完成第二次月地转移轨道修正,组合体上各系统状态良好[2]。
目前,顺利完成月球表面自动采样,五星红旗第一次月表动态展示,携带2 kg月球样品的嫦娥五号返回器即将着陆,预计于12月17日凌晨降落于内蒙古四子王旗。
图1 嫦娥五号月球钻取采样示意图
展望未来10年国际月球探测,三个显著趋势值得关注:一是月球无人探索仍是主旋律,航天大国向月表长期驻留发展,多个新兴航天国家则努力跻身月球俱乐部;二是载人登月重启,是人类不灭的梦想;三是月球成为未来载人深空探索的前哨站和跳板。
月球无人探索仍是主旋律
中美俄引领月球探索向深度进军
我国探月四期路线图清晰
中国自启动探月工程以来,按照“绕、落、回”三步走实施,最后的“回”是以“嫦娥五号”到月球正面取样返回作为标志,它们构成了探月一到三期任务。
探月四期项目共论证了四次任务,其中“嫦娥四号”作为先导任务已经取得成功;为2030年前建设我国月球无人科研站,现已基本明确了三次任务,分别为“嫦娥六号”、“嫦娥七号”和“嫦娥八号”任务[3]。
“嫦娥六号”和“嫦娥七号”均计划着陆于月球南极,具体着陆点选在月背还是正面,将根据“嫦娥五号”采样情况来定。
“嫦娥六号”仍将采样返回,“嫦娥七号”则将对月球的地形地貌、物质成分、空间环境进行一次综合探测。
“嫦娥八号”除继续进行科学探测外,还要进行一些关键技术的月面试验,比如采用3D打印技术利用月壤建造基地等。
中国、美国、俄罗斯和欧洲等国家都在论证是否在月球建立科研基地或者科研站,我国希望通过“嫦娥八号”验证部分技术,为各国未来共同建造月球科研基地开展前期探索[4][5]。
图2 未来我国月球无人科研站基本型
美国主导建设访问型空间站LOP-G
2020年4月2日,美国国家航空航天局(NASA)发布的《NASA月球持续探索和发展计划》,描绘了阿尔忒弥斯计划的思路,提出要在月球南极建一座“大本营”,组织一个四人小组前往LOP-G,重点发展机器人和载人任务结合的任务[6][7]。
LOP-G是基于国际空间站(ISS)框架,由NASA主导,ESA、俄罗斯国家航天集团公司(Roscosmos)、日本宇宙航空研发机构(JAXA)和加拿大航天局(CSA)等参与研发的近月空间站。
不同于长期有人照料的空间实验室,LOP-G作为一个访问型空间站,它将支持宇航员在月球轨道和月面上短期驻留,以及经月球中转往返火星及深空,开展科学探索的同时,兼顾太空安全和商业航天等目标。
俄罗斯探月理想丰满
俄罗斯围绕月球探索与开发出台了多项政策和计划,其月球无人探测器为先遣任务,继而开展载人登月,最终实现月球基地永久驻留,发展路线日渐清晰。
俄罗斯是目前唯一一个针对月球基地做出明确建设规划的国家,它不仅有参与美国主导的LOP-G项目的意愿,而且也制定了本国月球轨道站计划,为月球探索与开发领域可能率先取得重大突破奠定了基础。
根据2019年2月Roscosmos和俄罗斯科学院(RAS)联合制定的《月球综合探索与开发计划草案》[8],俄罗斯月球计划周期为2019—2040年,每5年为一个实施阶段,共4个阶段。
图3 俄罗斯月球计划实施路线图
第一阶段(2019—2025年)计划执行“月球-25”(Luna-25)、“月球-26”(Luna-26)、“月球-27”(Luna-27)、“生物-M2”(Bion-M2)和“返回-MKA”(Vozvrat-MKA)等任务。
第二阶段(2026—2030年)利用“月球-28”(Luna-28)实施月球极区土壤采样返回。
第三阶段(2031—2035年)全面开展月球科学实验。
第四阶段(2036—2040年)月球基地进入全面运行阶段。
但时至今日各个规划任务进展未达预期。
图4 俄罗斯月球基地示意图
ESA月球立方星竞赛两方案胜出
月球流星撞击探测器(The Lunar Meteoroid Impact Observer, LUMIO)[9]是ESA SysNova月球立方星竞赛的两个获胜概念之一,利用12U立方星探测可见光谱中的闪光,月背由于流星体撞击导致的月闪现象,测绘流星体撞击地图,以期提高对过去和现在太阳系内流星体撞击模式的理解,未来可发展成为月球预警系统[10]。
图5 LUMIO概念图
Lumio由意大利米兰理工大学、荷兰代尔夫特理工大学、瑞士洛桑联邦理工学院、挪威科技公司、莱昂纳多-芬梅卡尼卡股份公司和美国亚利桑那大学等机构共同开发[11]。
图6 LUMIO 流星碰撞闪光探测原理示意图
月球挥发物和矿物测绘轨道器(Volatile and Mineralogy Mapping Orbiter, VMMO)[12]是月球立方星竞赛的另一个获胜概念,亦是12U立方星。
VMMO将研究月球南极附近Shackleton撞击坑内的永久阴影区,测绘水冰地图,探测其他挥发物的分布情况,测量月球辐射,并建立辐射环境模型,帮助开发后续任务硬件,支持载人探索任务[13]。
VMMO由MPB通信公司、英国萨里空间中心、加拿大温尼伯大学和Lens研发公司等机构共同开发。
图7 VMMO任务示意图
多个航天国家跻身月球俱乐部
月球作为深空探测的试验场和载人深空探索的前哨站,吸引了全球航天国家的高度关注,除中美俄航天大国外,印度、英国等新兴航天国家也纷纷出手,或夯实自己月球俱乐部会员身份,或努力跻身月球俱乐部。
印度月船3号任务推迟至2021年实施
2020年7月,印度空间研究组织(ISRO)主席K Sivan指出,印度第三次探月任务有关的所有活动都在顺利进行[14]。
月船3号(Chandrayaan-3)推迟到2021年上半年发射[15],旨在实现月球软着陆,包括着陆器、巡视器和推进模块,与月船2号(Chandrayaan-2)任务的主要区别在于不包括轨道器。
图8 月船3号概念图
印度的首个载人航天项目Gaganyaan也将在2020年年底全面启动,计划于2022年发射,搭载航天员绕地球轨道运行7天后返回地球。
原计划于2020年12月的无人驾驶飞船任务因新冠疫情等原因推迟。
英国努力跻身月球俱乐部
英国私营公司Spacebit计划于2021年7月发射该国第一台月球车,以期使英国成为继美俄中之后,第四个完成此成就的国家。
仅1.5 kg的朝云蜘蛛月球车(朝の,Asagumo)将是史上最轻的月球车,其独特特点是有四条腿,外形酷似蜘蛛,不再是轮式[16]。
月球曾经经历火山活跃时期,喷发的熔岩在流动过程中顶层逐渐冷却,成为坚硬的岩石,下层熔岩流干或凝固后形成熔岩洞。
熔岩洞没有岩屑,是崎岖不平的岩石,适合这种腿形月球车攀上爬下,可为未来人类在月球熔岩洞建设永久基地做准备。
图9 朝云蜘蛛月球车示意图
另外,月球探路者卫星(Lunar Pathfinder)由英国的萨里卫星科技公司(Surrey Satellite Technology Limited)研制,将是首个提供高性能、有价格竞争力的地月间通信服务的商业绕月轨道器[17]。
图10 月球探路者示意图
月球探路者的第一个客户是ESA,并期望NASA成为其下一个大客户,为美国重返月球提供地月通信服务。
月球探路者将于2023年中后期全面投入商用服务,预计寿命8年。
该任务成功后,下一步还将发射更多月球卫星,组建月球版的GPS系统。
图11 月球探路者中继通信工作示意图[17]
日本表达未来继续探月的愿望
2020年7月,日本文部科学省(MEXT)大臣Hagiuda Koichi与NASA局长布莱登斯汀(James Bridenstine)共同签署月球联合探测意向,提出美日两国将共享阿尔忒弥斯计划目标[18],使日本航天员进入LOP-G和登陆月球。
JAXA的月球探测智能着陆器(Smart Lander for Investigating Moon)和月球极区探测任务(Lunar Polar Exploration mission)上将搭载NASA载荷,NASA月球探测任务上也同样会搭载JAXA的载荷,双方共享探测数据。
图12 JAXA的月球探测智能着陆器概念图
以色列欲继续未竟的探月任务
以色列首次登月任务“创世纪号”(Beresheet)月球着陆器,2019年4月软着陆失败在月表坠毁。
非营利组织SpaceIL宣布了第二次登月任务“创世纪2号”[19],多名私人投资者已表明为该任务提供资金的意向。
以色列也在争取成为第四个成功登陆月球的国家,侧面反映出某些航天国家月球探索的激烈竞争。
图13 创世纪号月球探测器
载人登月是人类不灭的梦想
中国和美国都有在未来载人登月的计划,拟在十年内将航天员送至月表进行科学探测。
当然,载人登月不是空间探索的终点,月球只是人类的跳板,目标还将人类送往火星及以远。
图 14 1969年11月20日,阿波罗12号舱外活动照片,后方是阿波罗12号登月舱,前面美国的勘测者3号,当时宇航员Charles Conrad Jr.和Alan L. Bean协作拆卸勘测者3号探测相机和零部件[20]
美国重返月球是阿尔忒弥斯第一阶段任务的核心
NASA发布的《前往月球:NASA月球探索战略规划》报告[21],介绍了阿尔忒弥斯载人月球探索计划框架及主要内容。
该计划的第一阶段目标是按照特朗普总统要求,2024年前将美国航天员送至月表,踏足迄今无人造访的月球南极,终极目标是将人类送往火星。
主要工作包括:利用“空间发射系统”(SLS)和“猎户座”(Orion)飞船执行3次阿尔忒弥斯任务,即2020年的“阿尔忒弥斯-1”无人飞行测试,2022年的“阿尔忒弥斯-2”载人飞行测试和2024年的“阿尔忒弥斯-3”载人登月任务。
图15 Artemis计划中宇航员在月表探测的概念图
特朗普政府一直呼吁在未来五年内增加对NASA的资助,以推动该机构的Artemis计划。
据悉,该项目旨在将首位女性和下一位男性送上月球表面。
最初计划在2028年首次着陆,但政府要求将时间提早至2024年。NASA已经明确表示,为了赶上更紧迫的最后期限,有必要大幅增加预算。
在2020年11月份,美参议院拨款委员会公布了下一年的12项拨款法案,新法案将向NASA拨款总计235亿美元,其中拨款10亿美元用于建造新的月球着陆器,但这比NASA的预算申请少了约24亿美元[22]。
美国总统换届导致航天政策的微调,以及资金短缺等原因,可能会推迟首位女性2024年登月计划的实现。
我国启动论证载人登月
嫦娥五号任务,可以看作十年后中国载人登月的预演。
嫦娥五号任务中分离和对接,与美国阿波罗计划载人登月的技术类似。
从2020年到2030年或2035年,我国将在10-15年的时间内遵循无人月球科研站基本型——载人登月——短期有人/无人月球科研站的路线,实现月球的开发。
然后用10年左右的时间,也就是在接近建国100周年时,建成综合型的月球基地[23]。
月球是载人登火的前哨站
图16 LOP-G示意图
如前文所述,NASA主导的LOP-G以载人火星探测为最终目标,并在LOP-G建成后,于2030年前进一步建设深空运输系统(DST),为2030年代中期实施载人火星探测任务奠定基础[24]。
图17 月球是载人登火的前哨站示意图
在载人登月、载人登火正在引发全球航天热潮之际,中国也形成了具有自身特色的航天经济、航天技术和航天文化,面向未来载人月球与火星探测任务,提出了以远轨太空港DRO轨道站为基础的近地轨道以远的航天发展战略。
图18 远轨太空港为基础的近地轨道示意图
浩瀚太空,月球探索是起点,也是各国实行太阳系行星探索和载人火星等深空任务不可或缺的关键环节。
未来10年月球探测任务值得关注。
参考文献
[1].http://www.clep.org.cn/n5982064/c6810467/content.html
[2].http://www.clep.org.cn/n5982341/c6810860/content.html
[3]. 邱家稳, 王强, 马继楠. 深空探测技术[J]. 红外与激光工程, 2020, 49(05): 9-18.
[4]. 景骢. “嫦娥五号”年底飞,后续相关规划首次公开[J]. 太空探索, 2019(03): 5.
[5]. 火星、小行星、木星系及行星穿越中国“深空天路”展望2030年[J]. 科学家, 2017, 5(19): 90-91.
[6]. 王琴, 范全林, 张晓雯. 美国月球轨道空间站建设启动实质研发[J]. 国际太空, 2019(04): 17-22.
[7]. 中俄欧航天局初步达成共识,将联合开展国际月球科研站论证[J]. 华东科技, 2019(08): 14.
[8]. 范唯唯, 杨帆, 韩淋, 王海名. 俄罗斯未来月球探索与开发计划解析[J]. 科技导报, 2019, 37(16): 6-11.
[9].https://www.esa.int/Enabling_Support/Space_Engineering_Technology/CubeSats_for_hunting_secrets_in_lunar_darkness
[10].https://directory.eoportal.org/web/eoportal/satellite-missions/content/-/article/lumio
[11].https://www.tudelft.nl/en/2020/lr/the-lumio-mission-a-cube-sat-watches-meteoroid-impacts-on-the-far-side-of-the-moon/
[12].https://meetingorganizer.copernicus.org/EGU2020/EGU2020-22678.html?pdf
[13].http://epubs.surrey.ac.uk/849054/1/__homes.surrey.ac.uk_home_.System_Desktop_ICES_2018_227.pdf
[14]. https://www.oneindia.com/india/isro-2020-target-set-to-launch-cost-effective-chandrayaan3-gaganyaan-3006598.html
[15].https://indianexpress.com/article/technology/science/chandrayaan-3-launch-date-isro/
[16].https://spacebit.com/
[17].https://www.sstl.co.uk/what-we-do/lunar-mission-services/lunar-pathfinder
[18].https://www.mext.go.jp/content/20200714-mxt_uchukai02-000008680_1.pdf
[19].https://www.timesofisrael.com/spaceil-chief-beresheet-2-starts-tomorrow-well-put-our-flag-on-the-moon/
[20].https://solarsystem.nasa.gov/resources/821/apollo-12-and-surveyor-3/
[21].https://www.nasa.gov/sites/default/files/atoms/files/america_to_the_moon_2024_artemis_20190523.pdf
[22].https://oig.nasa.gov/docs/IG-21-004.pdf
[23].https://new.qq.com/omn/20201201/20201201A01JRJ00.html
[24].https://nvite.jsc.nasa.gov/presentations/b2/D1_Mars_Connolly.pdf
来源:科技导报
来源: 国家空间科学中心
*请认真填写需求信息,我们会在24小时内与您取得联系。