史上最简单的 ThinkJS 七牛教程

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

七牛是提供了 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 评论

刘明野的博客 Chrome53.0 Windows 7
2016-10-03 11:52:01 回复

雁过留声,人过留名。

什么最值买 Chrome45.0 Windows 10
2016-09-11 07:25:30 回复

七牛的服务很不错

徒然 Chrome51.0 Windows 7
2016-09-07 13:26:17 回复

公子,请教下Typecho怎么实现“引用”功能,引用评论的内容。不知道怎么调用<blockquote>

公子 Chrome53.0 Mac OS 10.11.6
2016-09-11 02:35:08 回复

@徒然 你可以在后台开启允许评论使用 Markdown 语法,然后使用

> 我是一个 blockquote 

的语法来写 blockquote,或者直接在评论设置“允许使用的HTML标签和属性”中添加 <blockquote> 的标签即可。

徒然 Chrome51.0 Windows 7
2016-10-05 13:35:32 回复

@公子
啊!我表达有误,。。哈哈。我是不懂怎么实现那个功能 - -!像这个博客的回复旁边有个“引用”:http://www.woyigui.cn/guestbook/(不是广告!!)

公子 Chrome53.0 Mac OS 10.12.1
2016-10-06 10:42:26 回复

@徒然 那个呀,那个很简单的,你重写 replycomment 函数就好了,你可以参考我之前写的 At 插件,大同小异。

徒然 Chrome51.0 Windows 7
2016-10-07 00:33:07 回复

@公子好的,感谢!大致明白了!

故事会 Chrome43.0 Windows 7
2016-08-20 08:50:51 回复

js框架好多,学不过来了

themebetter QQBrowser9.4 Windows 8.1
2016-05-26 09:39:12 回复

终于搞定新主题tob上线,过来看看,博主好久没更新了呢?

斯托克笔记 IE11.0 Windows 10
2016-05-12 12:58:56 回复

好高端,小白表示看不懂。

奇草导航 Firefox45.0 Windows XP
2016-04-21 19:48:10 回复

网站标题适合做美女图片,JN站点。误点进来了。。

codetimecn.com Chrome49.0 Windows 7
2016-04-01 18:48:56 回复

公子,该更新博客啦! 我们聊的那一期上线了, 可以发个博客哟 😃

themebetter Chrome46.0 Windows 8.1
2016-03-21 13:05:23 回复

不过,网站名字与这技术内容是不是不太搭呀?

themebetter Chrome46.0 Windows 8.1
2016-03-21 13:04:48 回复

挺不错,学习了。

solarhell Chrome48.0 Mac OS 10.11.3
2016-03-02 10:50:24 回复

您觉得处理URL的逻辑是加在 src/home/controller/index.js 比较好还是加在 src/home/logic/index.js 比较好

公子 Chrome48.0 Mac OS 10.11.4
2016-03-02 13:43:52 回复

@solarhell 如果处理的 URL 需要后续处理的话还是放 controller 里头吧,如果只是用来做一些判断的就放 logic 里面吧。我觉得你可以先放在 controller 里面,最后如果你觉得它在 controller 里面有点显得多余,那就放 logic 里面吧。

solarhell Chrome48.0 Mac OS 10.11.3
2016-03-02 10:44:25 回复

有一点小小的问题 就是最后拼接出来的图片地址处理方面
要是没有在 src/home/config/config.js 在域名后加 “/” 可能需要再加一个判断 来给输出的拼接地址加上 “/”

公子 Chrome48.0 Mac OS 10.11.4
2016-03-02 13:41:09 回复

@solarhell 嗯,是的。可以强制在拼接的时候加上 / 这样就不会有问题了,感谢提醒。

solarhell Chrome48.0 Mac OS 10.11.3
2016-03-02 10:25:16 回复

写的很好,对于正在学习thinkjs的我很有帮助,谢谢博主!