史上最简单的 ThinkJS 七牛教程

提醒:本文最后更新于 2088 天前,文中所描述的信息可能已发生改变,请谨慎使用。

七牛是提供了 NodeJS 的 SDK 的,这就为我们的使用带来了极大的方便。我们需要知道以下四个信息:

有了以上基本信息之后我们就可以在 ThinkJS 的基础上添加七牛图床了!首先我们需要新建一个 ThinkJS 项目,在命令行中执行:

//如果没有 thinkjs 命令则首先需要 npm install -g thinkjs
$ thinkjs new thinkjs-niu --es6

我们可以进入项目根目录安装依赖然后 start 一下,然后访问 http://localhost:8360 就会发现我们的 ThinkJS 项目已经可以正常访问啦!

$ cd thinkjs-niu
$ npm install
$ npm start

之前我们说到七牛有自己的 NodeJS SDK,所以下一步我们要先把 SDK 安装上,进入项目根目录后执行:

$ npm install qiniu --save

将我们在最开始获取到的四个信息配置到 config 里面,打开 src/home/config/config.js 并按照如下所示补充内容:

'use strict';
/**
 * config
 */
export default {
  //key: value
  qiniu: {
    access_key: '你的 access_key',
    secret_key: '你的 secret_key',
    bucket: '你的空间名称',
    domain: '你的空间域名'    
  }
};

补充好后,继续打开 src/home/controller/index.js 并增加如下内容:

'use strict';

import Base from './base.js';
import qiniu from 'qiniu';

export default class extends Base {
  /**
   * index action
   * @return {Promise} []
   */
  indexAction(){
    let qconfig = this.config('qiniu');
    let putPolicy = new qiniu.rs.PutPolicy( qconfig.bucket );
    qiniu.conf.ACCESS_KEY = qconfig.access_key;
    qiniu.conf.SECRET_KEY = qconfig.secret_key;

    this.assign({
      uptoken: putPolicy.token(),
      baseUrl: qconfig.domain
    });

    return this.display();
  }
}

七牛上传图片需要三个关键的东西,一个是根据 key 生成的密钥 token,一个是文件的名称,最后一个当然是文件。通过 new qiniu.rs.PutPolicy(<bucket>).token() 方法我们就可以直接获取到生成的密钥了。这里不得不吐槽一下 qiniu.conf.ACCESS_KEYqiniu.conf.SECRET_KEY 这样的设定,直接在模块上增加属性我也是醉了。最后我们把生成好的 uptoken 和定义的空间域名传入到模板中就 OK 了!

下面我们开始写我们的模板吧!模板的编写其实非常简单,清空 view/home/index_index.html 文件并添加如下代码:

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>ThinkJS Qiniu Demo</title>
</head>
<body>
  <form method="post" action="http://upload.qiniu.com/"
   enctype="multipart/form-data">
    <input name="key" type="hidden" value="">
    <input name="token" type="hidden" value="<%=uptoken%>">
    <input name="file" type="file" required/>
    <button>OK</button>
  </form>
</body>
</html>

保存后我们访问 http://localhost:8360 就可以进行测试了。选择图片并点击 OK 按钮后会提交文件到七牛的服务器上,七牛会返回类似一下内容的 JSON 字符串:

{"hash":"lqRwoZzfZ6_2QHand2ix6AITjOw_","key":""}

其中 key 就是我们七牛线上保存的文件名,将其与空间域名拼接后就能获取到文件的 URL 地址了。不过此时我们会发现 key 是空的,那是因为我们并没有上传 key,代表着文件名为空。解决办法是在表单提交之前获取 file 控件的值并拿到文件名。同时我们还会发现由于是表单上传所以页面会进行跳转,为了不进行跳转我们必须将表单提交替换为 AJAX 模拟表单提交。按照如下代码修改模板:

<form method="post" action="http://upload.qiniu.com/"
   enctype="multipart/form-data" onsubmit="return send();">
  <input name="key" type="hidden" value="">
  <input name="token" type="hidden" value="<%=uptoken%>">
  <input name="file" type="file" required/>
  <button>OK</button>
</form>
<script>
/** 设置 key 值为文件名 **/
function setKey() {
  var key = document.querySelector('input[name=key]');
  var file = document.querySelector('input[name=file]');
  var filename = file.value.match(/[^\/\\]+\.\w+$/);
  if( !filename[0] ) {
    return false;
  }
  key.value = filename[0];
  return true;
}

/** 提交表单上传图片 **/
function send() {
  var xhr = new XMLHttpRequest(), button = document.querySelector("button");
  xhr.open("POST", "http://upload.qiniu.com", true);
  xhr.onload = function() {
    button.removeAttribute("disabled");
    button.innerText = "OK";
    
    var res = JSON.parse( xhr.responseText );
    prompt('你上传的文件地址是:', "<%=baseUrl%>"+res.key);
  }

  button.setAttribute("disabled", "disabled");
  button.innerText = "正在上传中...";

  setKey();
  xhr.send(new FormData(document.querySelector("form")));
  return false;
}
</script>

动态设置文件名 key,增加 AJAX 表单提交,并在表单提交时修改按钮文字表示正在上传,上传结束之后弹窗提示用户文件的七牛地址。这样整个流程就完美了!本教程完整的示例代码可以从这里下载:百度云 | 云盘(提取码:4fd4)。下载解压 npm install 之后直接 npm start 即可运行。

Avatar
怡红公子 擅长前端和 Node.js 服务端方向。热爱开源时常在 Github 上活跃,也是博客爱好者,喜欢将所学内容总结成文章分享给他人。

19 评论

2016-10-03T11:52:01.000Z 回复
雁过留声,人过留名。
2016-09-11T07:25:30.000Z 回复
七牛的服务很不错
2016-09+00T13:26:17.000Z 回复
公子,请教下Typecho怎么实现“引用”功能,引用评论的内容。不知道怎么调用`
`。
2016-09-11T02:35:08.000Z 回复
@徒然 你可以在后台开启允许评论使用 Markdown 语法,然后使用 ``` > 我是一个 blockquote ``` 的语法来写 blockquote,或者直接在评论设置“允许使用的HTML标签和属性”中添加 `
` 的标签即可。
2016-10-05T13:35:32.000Z 回复
@公子 啊!我表达有误,。。哈哈。我是不懂怎么实现那个功能 - -!像这个博客的回复旁边有个“引用”:http://www.woyigui.cn/guestbook/(不是广告!!)...
2016-10-06T10:42:26.000Z 回复
@徒然 那个呀,那个很简单的,你重写 replycomment 函数就好了,你可以参考我之前写的 [At 插件](https://github.com/typecho-fans/plugins/blob/master/At/Plugin.php#L62-L101),大同小异。
2016-10+00T00:33:07.000Z 回复
@公子好的,感谢!大致明白了!
2016-08-20T08:50:51.000Z 回复
js框架好多,学不过来了
2016-05-26T09:39:12.000Z 回复
终于搞定新主题tob上线,过来看看,博主好久没更新了呢?
2016-05-12T12:58:56.000Z 回复
好高端,小白表示看不懂。
2016-04-21T19:48:10.000Z 回复
网站标题适合做美女图片,JN站点。误点进来了。。
2016-04-01T18:48:56.000Z 回复
公子,该更新博客啦! 我们聊的那一期上线了, 可以发个博客哟 :)
2016-03-21T13:05:23.000Z 回复
不过,网站名字与这技术内容是不是不太搭呀?
2016-03-21T13:04:48.000Z 回复
挺不错,学习了。
2016-03-02T10:50:24.000Z 回复
您觉得处理URL的逻辑是加在 src/home/controller/index.js 比较好还是加在 src/home/logic/index.js 比较好
2016-03-02T13:43:52.000Z 回复
@solarhell 如果处理的 URL 需要后续处理的话还是放 controller 里头吧,如果只是用来做一些判断的就放 logic 里面吧。我觉得你可以先放在 controller 里面,最后如果你觉得它在 controller 里面有点显得多余,那就放 logic 里面吧。
2016-03-02T10:44:25.000Z 回复
有一点小小的问题 就是最后拼接出来的图片地址处理方面 要是没有在 src/home/config/config.js 在域名后加 "/" 可能需要再加一个判断 来给输出的拼接地址加上 "/"
2016-03-02T13:41:09.000Z 回复
@solarhell 嗯,是的。可以强制在拼接的时候加上 `/` 这样就不会有问题了,感谢提醒。
2016-03-02T10:25:16.000Z 回复
写的很好,对于正在学习thinkjs的我很有帮助,谢谢博主!