H5标签input标签上传文件(一)

本文介绍了一种使用H5 input标签实现图片上传的方法,并详细讲解了如何限制上传文件的类型和大小,确保前端数据的有效性和安全性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

之前项目做文件上传(本篇着重讲纯图片上传)的时候,一般都是用的flash插件。
H5的input标签提供了type=file的文件上传功能,那么如何用这个标签实现前后端之间的文件上传呢。
百度了一下,一个能用的都没有,都有BUG,讲的也很复杂,好气喔,自己写吧!

先看部分代码:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <title>H5input标签上传文件</title>
        <script type="text/javascript" src="jquery.min.js"></script>
    </head>

    <body>
        <input type="file" name="image" accept="image/*" onchange="uploadImg()">

        <script type="text/javascript">

            function uploadImg(event) {
                var e=window.event||event;
                // 获取当前选中的文件
                var oFile = e.target.files[0];
                console.log(oFile);//打印值看下面图片,简单点的话我们直接把这个数据给后台处理就可以了

                //接下来按照跟后台约定好的进行数据交互就可以-不使用jq的话这里有一些细节,稍后解释
                $.post("约定好的url地址",oFile,function(result){
                    console.log(result);
                })
            }
        </script>
    </body>

</html>

上面console.log(oFile);这一行代码打印的结果如下:
这里写图片描述
简单点,写博客的方式简单点,不要为了显摆自己的技术写一堆API文档都可以查到的东西。
这里给想深入了解的H5上传的同学三个相关的知识链接(没错,MDN上的API描述):
FormData
FileReader()
Blob()

上面只是一个简陋的方案(但完全可用),接下来让我们完善一下!

既然做的是单张图片上传功能,这里我在input标签上加了一个accept="image/*" 做了一个基本的类型限制,这样你在选择文件的时候你会发现你能选择文件类型是图片文件。
这里写图片描述

我们可以自定义可上传的文件类型,用如下方式指定多种类型:
<input type="file" accept=".doc,.docx,.pdf,.txt,.htm,.html" />

但是这并不能防止用户的恶意操作(主要是堵住测试和后台的嘴,☺),另外就算是选择类型是图片的话,其实还是可以选择少部分其它格式例如.zip。
利用之前给展示过的oFile打印结果中的type字段

// 检查上传文件类型--添加到发送数据之前
if(['jpeg', 'png', 'gif', 'jpg'].indexOf(oFile.type.split("/")[1]) < 0) {
    // alert太ugly了,用你们系统的报错弹窗就行(如果有)
    alert("上传的文件必须是图片格式");
    return;
}

好,图片的格式算是限制了,数组里面没涉及到的格式你自己往里面加。

额外补充一点,你会发现当我要做上传所有类型的文件时,通过oFile.type去判断文件类型好像有点问题,那么这里我提供一个稳妥的办法,我们通过oFile.name去判断,代码如下:

// 限制文件类型
var fileType = oFile.name.substr(oFile.name.lastIndexOf(".")+1);
if (['doc', 'docx', 'pdf', 'txt', 'htm', 'html'].indexOf(fileType) < 0) {
    alert("只支持.doc .docx  .pdf  .txt  .htm .html格式文件");
    return;
 }

上传文件的大小也限制一下,前端做限制很简单,利用之前oFile打印结果中的size字段,这里API给我们返回的是所选文件的字节数,1KB=1024字节,1MB=1024KB。利用以上,我们加个判断:

var imgMaxSize = 1024 * 1024 * 4; // 4MB图片的字节数
if(oFile.size>imgMaxSize){
    alert("您可上传文件的最大限制为4MB");
    return;
}

如果你用的是jquery.ajax,并且你上传的是文档文件,可能ajax会对你的文件进行预处理,然后你就可能遇到如下错误:
Illegal invocation这时候我们在ajax里面配置一下选项processData:false, 关掉jquery的预处理就行了,一般这种问题多发生在文档文件上。

$.ajax({
    type:'POST',
    url:url,
    data:formData,
    contentType:undefined,
    processData:false,            
    success:function(data){}
 });

还有一些东西,例如图片上传前压缩啊什么的,不想写长篇,这里先不讲了,在这里放一个简单完整版的代码,方便我自己以后copy,你们要用自己拿,别客气!

<!DOCTYPE html>
<html>

    <head>
        <meta charset="utf-8" />
        <title>H5-input标签上传文件</title>
        <script type="text/javascript" src="jquery.min.js"></script>
    </head>

    <body>
        <input type="file" accept="image/*" onchange="uploadImg()">

        <script type="text/javascript">
            function uploadImg(event) {

                var e = window.event || event;
                var oFile = e.target.files[0];
                //console.log(oFile);

                var imgMaxSize = 1024 * 1024 * 4; //4MB

                // 限制文件类型
                if(['jpeg', 'png', 'gif', 'jpg'].indexOf(oFile.type.split("/")[1]) < 0) {
                    alert("仅可以上传图片格式文件");
                    return;
                }

                //限制大小
                if(oFile.size > imgMaxSize) {
                    alert("文件最大为4MB");
                    return;
                }

                var data=new FormData();
                data.append("filesData",file);//这里不管怎样,我决定还是用formdata的方式上传。

                $.post("约定地址",data,function(result){
                    console.log(result);
                })

            }
        </script>
    </body>

</html>
<think>我们正在处理个关于HTML5中input type="file"元素如何触发拍照或上传文件功能的问题。根据用户的问题,我们需要结合移动端特性来实现调用相机或相册的功能。 根据引用[1]和引用[2]中的信息,我们可以通过设置input标签的`capture`和`accept`属性来实现不同的功能: 1. `accept`属性:用于指定上传文件的类型,例如`image/*`表示接受所有图片类型,`video/*`表示视频,`audio/*`表示音频。 2. `capture`属性:用于指定调用设备的哪个摄像头(前摄像头还是后摄像头),但更常见的是用于指定使用相机(camera)还是摄像机(camcorder)等。在移动端,设置`capture="camera"`可以触发拍照功能。 另外,引用[3]提到了在Android WebView中需要特殊处理才能支持文件上传,但用户的问题主要是关于HTML5的实现,所以我们先关注HTML5标准实现。 具体实现方式: - 如果希望直接调用相机拍照上传,可以这样写: ```html <input type="file" accept="image/*" capture="camera"> ``` 这里`capture="camera"`表示调用相机,`accept="image/*"`表示接受图片类型。 - 如果希望调用相册选择图片,则不需要`capture`属性,或者设置`capture`为其他值(如`capture="filesystem"`)可能无效,实际上,不设置`capture`属性时,浏览器会提供选项(相机、相册等)让用户选择。但不同浏览器行为可能不同。 另外,引用[2]还提到可以使用`mutiple`属性来支持多选。 因此,根据需求,我们可以这样设计: 1. 只拍照上传:使用`capture="camera"`和`accept="image/*"` 2. 只从相册选择:只设置`accept="image/*"`(不设置capture) 3. 同时支持拍照和相册:不设置capture,这样在移动端点击时,浏览器会弹出选择(可能包括“拍照”、“从相册选择”等选项) 注意:不同设备和浏览器支持程度不同,例如iOS和Android可能有不同的默认行为。 另外,引用[4]和[5]提供了关于上传音乐文件或其他文件类型的例子,我们可以通过改变`accept`属性来限制上传文件类型。 例如: - 上传视频:`accept="video/*"` - 上传音频:`accept="audio/*"` - 上传特定格式:`accept=".jpg,.png"` 总结代码: 1. 调用相机拍照(图片): ```html <input type="file" accept="image/*" capture="camera"> ``` 2. 调用相册选择图片(不限制拍照): ```html <input type="file" accept="image/*"> ``` 3. 调用相机拍照(视频): ```html <input type="file" accept="video/*" capture="camcorder"> ``` 注意:`capture="camcorder"`用于调用摄像机录制视频,但实际测试中,可能不同浏览器支持不同,有些浏览器可能用`capture="user"`(前置摄像头)或`capture="environment"`(后置摄像头)等,但标准中并未完全统。目前,`capture`属性在移动端浏览器中,对于图片,通常使用`camera`,对于视频,使用`camcorder`可能不被广泛支持,更通用的做法是只设置`accept`和`capture`(不带值)或使用媒体捕获规范。 另外,W3C的媒体捕获规范(Media Capture)定义了`capture`属性,可以取值为`user`和`environment`,分别表示前置摄像头和后置摄像头。例如: ```html <input type="file" accept="image/*" capture="environment"> ``` 表示使用后置摄像头(主摄像头)拍照。 但是,由于兼容性问题,我们通常简单使用`capture`(不带值)或`capture="camera"`。 因此,在实际开发中,为了兼容性,建议: - 需要拍照:使用`capture="camera"`和`accept="image/*"` - 需要录制视频:使用`accept="video/*"`,并可以加上`capture="camcorder"`(但注意,有些浏览器可能不支持,所以测试很重要) 最后,关于Android WebView的问题(引用[3]),如果我们的页面是嵌入在Android WebView中,那么可能需要客户端代码支持,重写WebChromeClient等方法,但这已经超出了HTML5的范畴。 所以,回答用户的问题:在HTML5中,使用input type="file"元素,通过设置`capture`和`accept`属性,可以触发拍照或上传文件功能。 下面给出个完整的示例代码: ```html <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>文件上传示例</title> </head> <body> <h3>拍照上传(仅拍照)</h3> <input type="file" accept="image/*" capture="camera"> <h3>从相册选择图片</h3> <input type="file" accept="image/*"> <h3>录制视频上传</h3> <input type="file" accept="video/*" capture="camcorder"> <h3>选择视频文件(不指定capture)</h3> <input type="file" accept="video/*"> <h3>上传音频文件</h3> <input type="file" accept="audio/*"> </body> </html> ``` 注意:以上代码在移动设备上测试效果更明显。 另外,用户可能还需要知道如何在上传前预览图片,但用户的问题没有提到,所以不展开。 最后,生成相关问题: 1. 如何限制上传文件的大小? 2. 如何实现多文件上传? 3. 如何在上传前预览图片? 4. 在Android WebView中如何支持文件上传? 5. 如何通过JavaScript监听文件选择事件并获取文件信息? 根据以上思路,整理回答。</think>### HTML5 input type="file" 拍照与上传文件实现指南 在HTML5中,通过`<input type="file">`元素结合特定属性,可以实现在移动端调用相机拍照或选择相册文件上传的功能。核心实现方式如下: #### 1. **基础拍照上传** ```html <!-- 调用后置摄像头拍照 --> <input type="file" accept="image/*" capture="camera"> <!-- 调用前置摄像头自拍 --> <input type="file" accept="image/*" capture="user"> ``` - `accept="image/*"`:限制只接受图片文件 - `capture="camera"`:强制调用摄像头(默认后置) - `capture="user"`:调用前置摄像头(自拍模式) - 在iOS/Android设备点击时会直接启动相机[^1][^2] #### 2. **相册选择与拍照混合模式** ```html <!-- 同时允许拍照和相册选择 --> <input type="file" accept="image/*"> ``` - 不添加`capture`属性时,移动端会弹出选择菜单(相机/相册/文件管理器) - 支持多选:添加`multiple`属性[^2] #### 3. **扩展文件类型控制** | 文件类型 | 代码示例 | 设备行为 | |----------------|-----------------------------------|------------------------| | 视频录制 | `accept="video/*" capture` | 启动摄像机 | | 音频录制 | `accept="audio/*" capture` | 启动麦克风 | | 指定文件格式 | `accept=".jpg, .png, .pdf"` | 过滤显示指定格式文件 | | 多类型混合 | `accept="image/*,video/*"` | 同时显示图片和视频 | #### 4. **Android WebView特殊处理** 在Android WebView中需重写客户端方法: ```java // Java示例:重写WebChromeClient webView.setWebChromeClient(new WebChromeClient() { @Override public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) { // 在此触发原生相机/相册 return true; } }); ``` 需原生代码支持文件上传功能[^3] #### 5. **最佳实践与注意事项** 1. **跨平台兼容** - iOS 14+:全功能支持 - Android:需注意WebView兼容性 - PC端:`capture`属性会被忽略 2. **安全限制** - 必须通过用户交互(点击)触发 - HTTPS环境下才能调用摄像头[^2] 3. **扩展功能实现** ```javascript // 监听文件选择事件 document.querySelector('input').addEventListener('change', (e) => { const file = e.target.files[0]; if(file.type.startsWith('image/')) { console.log("图片尺寸:", file.size, "bytes"); } }); ``` 4. **界面优化建议** - 隐藏原生input样式,通过自定义按钮触发 - 使用`<label for="fileInput">`关联触发元素 >[!TIP] > 在真机测试时,不同厂商设备可能有差异,建议在iOS Safari和Android Chrome分别验证
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值