云课堂服务器 文件上传是常见需求,一般我们不会把文件直接上传到应用服务器,因为单台服务器存储空间是有限的,不好扩展。 我们会用单独的 OSS (Object Storage Service)···
云课堂服务器
文件上传是常见需求,一般我们不会把文件直接上传到应用服务器,因为单台服务器存储空间是有限的,不好扩展。
我们会用单独的 OSS (Object Storage Service)对象存储服务来上传下载文件。
比如一般会买阿里云的 OSS 服务。
我们本地文件存储是目录-文件的组织方式:
而 OSS 服务的存储结构是这样的:
一个桶里放一些文件。
云部署服务器
阿里云 OSS 的控制台也提到了对象存储没有目录层级结构:
但下面明明是支持目录的呀:
这其实只是模拟实现的。
Object 会存储 id、文件内容、元数据三部分信息:
阿里云 OSS 只是用元信息部分模拟实现了目录。
就像打了个 tag 一样,并不是说文件存储在这个 tag 下,只是你可以用这个 tag 来检索文件。
除了对象存储 OSS,阿里云也提供了文件存储和块存储的方式:
块存储就是把整块磁盘给你用,你需要自己格式化,存储容量有限。
文件存储就是有目录层次结构,你可以上传下载文件,存储容量有限。
对象存储就是 key-value 存储,分布式的方式实现的,存储容量无限。
这些简单了解就行,绝大多数情况下,我们都是用 OSS 对象存储。
我们买个阿里云的 OSS 服务来试试看:
我买了 40G 的 OSS 国内通用资源包,花了 5 块钱。
然后我们创建个 Bucket(桶):
在北京创建了一个 Bucket,文件就会存储在那里的服务器上。
设置公共读,也就是这些文件大家都可以直接访问。
不然私有的方式,你访问每个文件都要带上一些身份信息:
有的同学说,不是静态文件要在全国各地都能访问到么?存在北京的服务器会不会访问速度慢?
这是 CDN 的活:
接入 CDN 后,访问该域名会走到云服务的 DNS,然后返回一台最近的缓存服务器的地址,这台服务器会从源站拿文件来缓存,之后就不再访问源站。
这里的源站就可以是 OSS 服务。
创建 Bucket 之后,我们上传个文件试试:
上传完之后在文件列表就可以看到这个文件了:
点开可以看到文件详情,用这个 URL 就可以访问:
当然,生产环境下我们不会直接用 OSS 的 URL 访问,而是会开启 CDN,用网站域名访问,最终回源到 OSS 服务:
在控制台里上传很简单,那如果想在代码里上传呢?
官方文档里有示例代码,我们试试看:
mkdiross-testcdoss-testnpminit -y安装用到的包:
npminstallali-oss写下代码:
constOSS =require(ali-oss)constclient =newOSS({region:oss-cn-beijing,bucket:guang-333,accessKeyId:,accessKeySecret:, });asyncfunctionput(){try{constresult =awaitclient.put(cat.png,./mao.png);console.log(result); }catch(e) {console.log(e); } } put();region 在概览里可以看到:
这里的 accessKeyId 和 acessKeySecret 是什么呢?
本来我们身份认证都是通过用户名密码:
但这样不够安全,所以我们创建了 accessKey 用来代表身份,用它来做身份认证,就算泄漏了,也不影响别的:
我们创建个 accesKey:
创建完成后,拿到 accesKeyId 和 accessKeySecret 后运行代码:
这里的 mao.png 是这样的:
在控制台可以看到上传成功了:
这就是 OSS 用 api 上传文件的用法。
只是我们刚刚用的 accessKey 不够安全。
打开 accessKey 管理页面的时候就提示了:
让我们不要直接用 accessKey,而是创建一个子用户再创建 accessKey。
那我们就创建个子用户:
然后用这个 accessKey 的 id 和 secret 就好了:
但你直接换上它还不行:
会提示你 403,没有权限。
需要你授权下:
新增一个授权:
把 OSS 的管理和读取权限给这个子用户:
然后再试下:
这时候就上传成功了。
回过头来看下,不得不说阿里云在安全这一块设计的就很巧妙。
云派服务器满了
如果我们直接用用户名密码验证呢:
那万一泄漏了不就完蛋了么?
但是如果创建个 accessKey 用它来做身份认证:
就算泄漏了我也可以禁用啊:
再进一步,直接用这个 accessKey 它是有所有权限的。
我们先创建个 RAM 子用户,再分配给他某些权限,这样就算泄漏了,是不是能做的事情就更少了?
当然就更安全。
所以说,阿里云这套 accessKey 和 RAM 子用户的身份认证方式,还是很不错的。
再说回 OSS,一般的文件直接上传就行,涉及到大文件就要分片上传了。
分片上传实现原理是前端常见面试题了,大家都能答上来。
就是把文件用 slice 方法分成一个个小的片,然后全部上传完之后请求一个接口合并分片。
阿里云的大文件分片上传也是这样实现的:
具体怎么用直接看文档就好了,这里我们就不试了:
有了 OSS 服务之后,我们上传文件还需要经过应用服务器么?
可以经过也可以不经过。
如果经过应用服务器,那就要客户端上传文件之后,我们在服务里接受文件,上传 OSS:
这样当然是可以的,还能保护 accessKey 不被人窃取。
只是会浪费应用服务器的流量。
那如果不经过呢?
在客户端用 accessKey 把文件传到 OSS,之后把 URL 传给应用服务器就好了。
这样减少了应用服务器的流量消耗,但是增加了 accessKey 暴露的风险。
各有各的坏处。
那有没有啥两全其美的办法呢?
有。
阿里云的文档里也提到了这个问题。
它给出的解决方案就是生成一个临时的签名来用。
代码是这样的:
constOSS =require(ali-oss)asyncfunctionmain(){constconfig = {region:oss-cn-beijing,bucket:guang-333,accessKeyId:,accessKeySecret:, }constclient =newOSS(config);constdate =newDate(); date.setDate(date.getDate() +1);constres = client.calculatePostSignature({expiration: date.toISOString(),conditions: [ ["content-length-range",0,1048576000],//设置上传文件的大小限制。] });console.log(res);constlocation =awaitclient.getBucketLocation();consthost =`http://${config.bucket}.${location.location}.aliyuncs.com`;console.log(host); } main();上传 OSS 的地址,用的临时 signature 和 policy 都有了:
这些代码不用记,文档里都有:
这样就能在网页里用这些来上传文件到 OSS 了:
创建个 index.html
html><htmllang="en"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>Document
发表评论
最近发表
标签列表