#9 ng-file-upload文档

文件select和drop

使用插件则ngf-selectngf-drop 必须强制使用一个.

ngf-select选择相关的其它指令,一般使用*作为前缀

ngf-drop拖放相关的其它指令,一般使用+作为前缀

具体使用

// 使用标签可以为下面3个中的任意1个
<div|button|input type="file"|ngf-select|ngf-drop>
</div|button|input>

1.标签中的属性

#1

ngf-select="" 或者 ngf-select="upload($files, ...)" // 方法当文件选中或被清除时被调用
ngf-drop="" 或者 ngf-drop="upload($files, ...)"  // 当文件被放置的时候方法被调用

可以使用 ng-model 或者 ngf-change 来代替下面函数中的参数

#2

ngf-change="upload($files, $file, $newFiles, $duplicateFiles, $invalidFiles, $event)" // 当文件被选中,放置或清除时方法调用
ng-model="myFiles" // 绑定有效选择或放置的文件到作用域模型, 可以是数组或字符串, 这个由 `ngf-multiple` 和 `ngf-keep`值决定

#3

// updateOn 用于禁用点击重置或粘贴更新,浏览器图片放置等
// allowInvalid 默认值为false, 允许模型(model)中存在无效文件
// debounce 用于延时模型更新(单位为ms)
ng-model-options="{updateOn: 'change click drop dropUrl paste', allowInvalid: false, debounce: 0}"

// 将无效选择的文件或放置文件绑定到模型上
ng-model-invalid="invalidFile(s)"

// 在模型改变, 验证和resize之前,在文件被选择或放置之后被调用
ngf-before-model-change="beforeChange($files, ...)"

#4

// 禁用这个元素
ng-disabled="boolean"

// 默认值为false, 对这个元素禁止选择/放置文件
ngf-select-disabled="boolean"
ngf-drop-disabled="boolean"

// 默认值为false,是否允许选择多个文件
ngf-multiple="boolean"

// 默认值为false, 是否保留先前模型中的文件和后面添加的新文件
// 'distinct' 移除重复的文件, '$newFile', '$duplicateFiles' 在 ngf-change/select/drop 函数中设置
ngf-keep="true|false|'distinct'"

#5

// 默认值为false, 用于旋转包含 exif orientation数据的jpeg图片文件
ngf-fix-orientation="boolean"

#6

// 允许移动设备通过相机来添加图片
*ngf-capture="'camera'" 或者 *ngf-capture="'other'"

// 标准HTML接收的属性,浏览器选择时弹出窗口
*ngf-accept="'image/*'"

// 默认值为true, 允许放置文件,只针对chrome webkit 浏览器
+ngf-allow-dir="boolean"

// 默认值为false,在文件放置数据中包含路径
+ngf-include-dir="boolean"

#7

// 默认值为 'dragover', 拖动时添加css class, 可以是一个字符串,或一个函数返回类名或json对象
// 'accept/reject' class 只用于在chrome
+ngf-drag-over-class="{pattern: 'image/*', accept: 'acceptClass', reject: 'rejectClass', delay: 100}"
                或者 "'myDragOverClass'"
                或者 "'calcDragOverClass($event)'"

// 依据浏览器是否支持文件drag&drop来设置作用域的值为true或者false
+ngf-drop-available="dropSupported"                

// 默认值为false, 是否冒泡 拖拽事件
+ngf-stop-propagation="boolean"

// 默认值为false, 隐藏元素。如果文件拖拽不存在
+ngf-hide-on-drop-not-avaliable="boolean"

#8

ngf-resize="{width: 100, height: 100, quality: .8, type="image/jpeg",
             ratio: '1:2', centerCrop: true, pattern=".jpg", restoreExif: false
            }"
// 或者
// 函数返回一个promise
// resolve则获取选项: resize图片大小为给定的宽高或ratio; quality为可选的,范围为0.1-1.0
// type: 可选,转换为指定的图片格式
// centerCrop: 默认值为false, 不对图片进行裁剪,将适应给定的宽高或比率; 设置为true将不适应给定宽高的图片进行裁剪,可能导致图片宽或高小于给定的宽或高
// pattern:只对名字或类型相匹配的文件进行resize, 和'ngf-pattern'类似
// restoreExif: 默认值为true, 将修复resize 图片的exif信息
ngf-resize="resizeOptions()" 

// 只用这个函数返回为true才使用 'ngf-resize'属性
ngf-resize-if="$width > 1000 || $height > 1000"
          或者 "resizeCondition($file, $width, $height)"

// 默认值为false, 如果设置为true,则所有验证将在图片被rezise之后进行,因此在resize之前的验证错误将会被忽略
ngf-validate-after-resize="boolean"          

#9

验证

// 允许选择或放置的最大文件数量,验证错误名: maxFiles
ngf-max-files="10"      

// 允许选择文件类型,逗号分割用于过滤文件名和类型
// 排除不允许的文件类型使用 '!', 验证错误名: pattern
ngf-pattern="'.pdf,.jpg,video/*, !.jop'"

// 文件大小的验证
ngf-min-size
ngf-max-size
ngf-max-total-size = "100"(单位为bytes) 或者 "'10KB'" 或者 "'10MB'" 或者 "'10GB'"

// 对图片尺寸进行验证
ngf-min-height
ngf-max-height
ngf-min-weight
ngf-max-weight = "1000"(单位 px)

ngf-ratio="8:10, 1.6" // 指定的image ratio格式

ngf-dimensions="$width > 1000 || $height > 1000"
               "validateDimension($file, $width, $height)"

// 对视频或音频文件进行验证
ngf-min-duration
ngf-max-duration= "100.5"(单位 s) 或者 "'10s'" 或者 "'10m'" 或者 "'10h'"

ngf-duration="$duration > 1000"
             "validateDuration($file, $duration)"

// 上面所有验证的简写
ngf-validate="{size: {min: 10, max: '20MB'}, 
               width: {min: 100, max: 10000},
               height: {min: 100, max: 300},
               ratio: '2x1',
               duration: {min: '10s', max: '5m'},
               pattern: '.jpg'
              }"     

// 自定义验证函数,返回布尔值或包含错误的string
ngf-validate-fn="validate($file)"   

// 自定义验证函数,返回一个promise
ngf-validate-async-fn="validate($file)"   

// 默认值为false,如果设置为true, 'file.$error' 将被设置
// 例如图片加载错误或浏览器不支持的视频
// 默认情况会将设文件是有效的,如果浏览器不能计算出duration或dimension
ngf-validate-force="boolean"

// 忽略指定验证类型的错误
ngf-ignore-invalid="'pattern maxSize'"

#10

其它

<div|input|button ngf-no-file-drop>文件拖拽不支持</div|...>

// 将文件转换为base64 data url
<a href="file | ngfDataUrl">image</a>

2.文件预览

使用方式:

<img|audio|video|div
// 属性
>

可选属性有:

// 预览选择的文件,设置src属性为文件的data url
*ngf-src="file" 

// 给文件设置背景图片样式
*ngf-background="file"

// 在设置为src或背景图片前resize 图片(只对图片有效)
ngf-resize="{width: 20, height: 20, quality: 0.9}"

// 强制base64 url代替对象url, 默认值为false
ngf-no-object-url="true or false"

另外对图片:

<div|span|...
  *ngf-thumbnail="file" // 产生图片文件的缩略图
  ngf-size="{width: 20, height: 20, quality: 0.9}" // 图片将缩放为这个尺寸
  ngf-as-background="boolean" // 如果为true,则设置为背景图片而不是src属性
>

3.上传服务 Upload service

var upload = Upload.upload({
   // 配置信息
})

配置信息

#1 上传地址
*url: 'server/upload/url', // 可以为 upload.php脚本,node.js路由, 或者 servlet url

#2 上传数据
*data: {key: file, otherInfo: uploadInfo}
// 指定文件和发送到服务器的可选数据,每个包含嵌套对象的字段将以 'form data multipart' 形式发送
// 示例
{pic: file, username: username}
{files: files, otherInfo: {id: id, person: person, ...}}
{profiles: {
    [
        {pic: file1, username: username1},
        {pic: file2, username: username2}
    ] // 嵌套数据包含多个文件(html5)
}}
{file: file, info: Upload.json({id: id, name: name, ...})} // 将字段以json字符串格式发送
{picFile: Upload.rename(file: 'profile.jpg'), title:tile}

#3 请求方式
method: 'POST'(默认值) || 'PUT'(HTML5)

#4 头文件
headers: {'Authorization': 'xxx'} // (HTML5)

#5 是否带有凭证
withCredentials: boolean

#6 可恢复上传(HTML5)
resumeSizeUrl: '/upload/size/url?file=' + file.name // 目前上传到服务器文件的大小
resumeSizeResponseReader: function(data) {return data.size;} // 读取上传的文件大小从 resumeSizeUrl GET response中
resumeSize: function() {return promise;} // 返回一个promise,用于计算上传到服务器文件的大小
resumeChunkSize: 1000 || '10KB' || '10MB' // 以块上传指定的文件大小

#7 是否取消进度条
disableProgress: boolean // 默认值为false

#8 其它 angular '$http()' 选项可以这这里使用

上面的 var upload是一个promise,有如下的一些方法

upload.then(function(resp) {
    // 文件上传成功
    console.log('file ' + resp.config.data.file.name + 'is uploaded successfully. Response: ' + resp.data);
}, function(resp) {
    // 处理错误
}, function(evt) {
    // 进度通知
    console.log('progress: ' + parseInt(100.0 * evt.loaded / evt.total) + '% file : ' + evt.config.data.file.name);
});

// 捕获异常
upload.catch(errorCallback)
upload.finally(callback, notifyCallback);

// 访问底层XMLHttpRequest或者添加事件listeners
upload.xhr(function(xhr) {
    xhr.upload.addEventListener(...)
});

// 取消或终止上传过程

其它的上传方式和其它操作

发送文件二进制文件的content-type, 可用于将文件上传到CouchDB, imgur等,html5 FileReader接口是必要的, 这相当于angular $http(),但是允许你html5浏览器的progress事件进行监听

Upload.http({
    url: '/server/upload/url',
    headers: {
        'Content-Type': file.type
    },
    data: file
})

// 给ngf-select, ngf-drop指令设置默认值
Upload.setDefaults({ngfMinSize: 2000, ngfMaxSize: 200000, ....0})

// 转换单个文件或数组文件为base64 data url形式的单个或数组文件
// 用于在json内部以base64格式发送给数据库
Upload.base64DataUrl(files).then(function(urls){...})

// 将文件转换为二进制url对象或者base64数据url 依据 'disallowObjectUrl' 值
Upload.dataUrl(file, boolean).then(function(url) {...});

// 获取图片文件的围度
Upload.imageDimensions(file).then(function(dimensions){console.log(dimensions.width, dimensions.height);});

// 获取 audio/video 时长
Upload.mediaDuration(file).then(function(durationInSeconds){...});

// 修改图片尺寸, 返回一个promiase
// 选项 width, height, quality, type, radio, centerCrop, resizeIf, restoreExif
// resizeIf(width, height) 返回布尔值
Upload.resize(file, options).then(function(resizeFile){...})

// 返回布尔值,是否浏览器支持图片尺寸缩放
Upload.isResizeSupported()

// 是否浏览器支持可继续上传,返回布尔值
Upload.isResumeSupported()

// 给上传文件重命名
Upload.rename(file, newName)

// 将对象转换为application/json文件类型的二进制对象(HTML5)
Upload.jsonBlob(obj)

// 和angular.toJson(obj)一样
Upload.json(obj)

// 如果正在上传则返回true
Upload.isUploadInProgress()

// 检查对象是否为文件,可用于 Upload.upload()/http() 中
Upload.isFile(obj)

4.注意事项

ng-model

ng-model 的值将为单一文件而不是数组,如果全部满足下列情况:

  • ngf-multiple 没有设置或设置为false
  • multiple: 没有设置该属性
  • ngf-keep: 没有设置或设置为false

validation

当表单中指定的任何验证指令生效,我们可以通过 myForm.myFileInputName.$error.<validate error name> 使用验证值, 例如 form.file.$error.pattern.如果允许选择多个文件,可以指定 ngf-model-invalid="invalidFiles",将无效文件赋给模型,通过 file.$error 找到错误和file.$errorParam找到错误描述。可以使用angular的 ngf-model-option="{allowInvalidL: true}" 允许给ng-model设置无效文件

上传多个文件

只对 HTML5 FormData浏览器(非IE8-9), 有一个数组的文件或超过一个文件在 data 以一个请求发送他们。非html5浏览器由于falsh限制,只能一次请求上传一个文件。可以迭代文件,一个一个的上传文件

Upload.setDefaults(options): 如果有多个文件选择或拖拽,可以给它们设置默认值。 options是一个json对象,使用camalCase命名

拖拽样式

对于文件拖拽, ngf-drag-over-class 能够用于给drop区域添加样式。可以是一个依据$event返回class name的函数。 默认是 dragover字符串。只有chrome可以是一个json对象 {accept: 'a', 'reject': 'r', pattern: 'image/*', delay: 10}

5.老浏览器

对于不支持HTML5 FormData(IE8, IE9)的浏览器,将会使用 FileAPI 模块。注意需要在浏览器中安装flash,因为FileAPI需要使用Flash上传文件。

有2个文件: FileAPI.min.js, FileAPI.flash.swf 将被模块按需加载(如果浏览器支持html5表单数据就没必要包含在html中)。可以将这2个文件放在服务器angular-file-upload-shim(.min).js旁,自动的从相同的路径加载或者指定这些文件所在的路径,如果他们在不同的路径下:

<script>
  // 在 angular-file-upload-shim(.min).js之前被加载
  FileAPI = {
      // 只需要下面中的一个
      jsPath: '/js/FileAPI.min.js/folder/',   // 放本地上
      jsUrl: 'yourcdn.com/js/FileAPI.min.js', // 放服务器上

      // 只需要其中一个静态路径或flashUrl:
      staticPath: '/flash/FileAPI.flash.swf/folder/',
      flashUrl: 'yourcdn.com/js/FileAPI.flash.swf'

      // forceLoad: true, html5: false 
      // noContentTimeout: 10000
  }
</script>
<script src="angular-file-upload-shim.min.js"></script>

老浏览器已知的bug

  1. 由于flash的限制,如果服务器没有发送任何response body,响应状态码,则将永远是 204 ''No Content,所以如果要访问服务器上传码,至少需要返回一个状态码才能正常工作
  2. 自定义headers,不支持
  3. 由于flash bug, Server HTTP 错误码400将以200返回给客户端。因此避免从服务端返回上传响应的结果状态码400,因为客户端会以200当作成功
  4. 错误响应(http code >= 400) 自定义错误信息,由于flash,将不支持
  5. 不允许 'PUT' 请求
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,445评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,889评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,047评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,760评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,745评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,638评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,011评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,669评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,923评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,655评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,740评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,406评论 4 320
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,995评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,961评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,023评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,483评论 2 342

推荐阅读更多精彩内容