把图片上传到云上

在一个web应用中上传图片是一个很常见的功能,但是对于我这种前端的新手来说,费了好大的劲才把整个流程弄通。

最近尝试把原来网站的图片迁移到腾讯的图片云上(包括上传和下载的功能)。一开始研究了一下整个请求的流程,觉得还是挺简单的。

  1. 首先在自己的服务器中部署腾讯图片云的验证服务器,主要作用是在每次上传的时候分配上传的url和sign.(这部分的部署在文档中讲的很清楚了,也有现成的代码,就不多说了)
  2. 在每次上传图片前,浏览器向验证服务器请求一个上传的url(sign作为一个参数拼接在url后面)
  3. 发送ajax请求至第二步中获得的url,上传成功后会得到一个下载链接(download_url),之后通过这个链接查看(下载)图片

以上是最简单的流程,已经能够完成将图片上传到图片云并且浏览(下载)的功能。

可是完成这些功能还不够,为了和目前流行的上传图片的控件结合起来,还是有很长的路要走的。

那些现成的上传图片的控件,基本上都有以下特征:

  • 漂亮的UI
  • 上传图片预览(这个可以用浏览器的api取得一个待上传图片的地址,自己写起来也简单)
  • 包装好的各种事件,方便个性化定制

但是这些控件都有一个共同的缺点,上传的url是在初始化这个控件的时候确定的。

比如jQuery-File-Upload, 这是在github上star最多的一个图片上传控件,他的默认设置上传url的地方就三处,第一个是在初始化对象的时候,第二个是当前所在form下的action的地址,第三个是当前页面的url.

然而上面提到的,每个图片的上传地址是不一样的,这样就是需要在每次上传前修改这个地址,我尝试在submit之前去修改ajax option中的url字段,但是没法获得这个对象。

既然没法走通原有的模式,只能阻止原先的发送逻辑。

在options中有个属性叫submit, 官方的文档是这么说的

submit

Callback for the submit event of each file upload. If this callback returns false, the file upload request is not started.

只要在submit的时候return false,原有的表单就不会被上传,然后在submit的方法中写自己的上传逻辑。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
submit: function (e, data) {
if (data.files < data.files.length) {
$.each(data.files, function(i,value) {
$.getJSON("http://127.0.0.1:3000/doAction/picauthtest",
function(ret) {
var sign = encodeURIComponent(ret.data.sign);
var url = ret.data.url + '?sign=' + sign;
var formData = new FormData();
formData.append("filecontent", value);
var options = {
type: 'POST',
url: url,
dataType: 'json',
data: formData,
contentType : false,
processData : false,
success:function(ret) {
alert("第"+(i+1)+"张图片上传成功");
$("#downloadUrl").append(ret.data.download_url);
},
error:function (ret) {
alert("第"+(i+1)+"张图片上传失败("+ret.responseText+")");
}
};
$.ajax(options);
});
});
} else {
alert("没有文件可以上传");
}
return false;
}

jQuery-File-Upload这个控件是目前最流行的图片上传控件,可是还不支持针对不同文件设置不同上传url的功能(或许是已经支持只是我没有找到方法),而将图片上传到云上(腾讯图片云)却需要针对每个文件设置特定的url。用这个办法可以暂时解决这个问题,但是如果要显示每个上传文件的进度,或者取消上传等更加复杂的操作,还需要做其他工作。