js实现文件下载

复制代码 代码如下:

在自动化测试过程中,有时候需要上传文件,比如类似合同新建等功能必须要求强制上传附件。
附件上传的页面控件有两种情况

图片 1

https://scarletsky.github.io/2016/07/03/download-file-using-javascript/
http://blog.csdn.net/androidmi/article/details/7519243

var strCert=“ssssss”;
var fso=new ActiveXObject(“Scripting.FileSystemObject”);
var f=fso.CreateTextFile(“C:\\abc.cer”,true); //可随意选择后缀名
f.write(strCert);
f.Close();

第一种,Html原生的input file控件,也就是input标签中type=”file”;
第二种,通过其他一些方式实现的上传功能,比如swfupload.js。

图片 2

通过ajax请求服务器实现文件下载是我们在网页开发过程中经常遇到的需求,我的解决方案有两种:

代码如下: var strCert=“ssssss”; var
fso=new ActiveXObject(“Scripting.FileSystemObject”); var
f=fso.CreateTextFile(“C:\\abc.cer”,true); //可随意选择后缀名…

对于第一种文件上传也就是input控件的方式,

首先,将以下js代码放入页面这里我判断的是只能上传xls格式的文件,可以根据自己的需求修改js中的checkExcel方法

有可用的url

这种情况下可以可以通过创建<a>并模拟点击来实现唤醒下载窗口,代码如下:

let a = document.createElement('a');
a.href = url;
a.download = 'filename.txt';
a.click();

只要为<a> 标签添加
download属性,我们点击这个链接的时候就会自动下载文件了。download
的属性值是可选的,它用来指定下载文件的文件名。

<div>
  选择文件
  <input type="file" id="upload_pic">
</div>

</pre><pre name=”code” class=”javascript”><script
type=”text/javascript”> 
    var __FILE_INDEX = 0; //文件标识    
    var __LOADING_TIP_DIV = null; 
    var __ICON_PATH = “<%=Request.ApplicationPath%>/Images”; 
    /**  
    * 对选择的文件进行格式校验,只能选择xls格式的文件  
    */ 
    function checkFile(fileObj) { 
        var objSpan = document.getElementById(“span_” + fileObj.id); 
        if (!checkExcel(fileObj.value)) { 
            objSpan.innerHTML = “<img title=’错误’ src='” +
__ICON_PATH + “/check_error.png’ border=’0′></img><font
style=’color:red;font-size:12px’>只能导入xls格式文件!</font>” 
            fileObj.errFlag = true; 
        } else { 
            objSpan.innerHTML = “<img title=’正确’ src='” +
__ICON_PATH + “/check_right.png’ border=’0′></img>” 
            fileObj.errFlag = false; 
        } 
        if (fileObj.value != “” && fileObj.noDelete != “true”) { 
            document.getElementById(“del_” + fileObj.id).innerHTML =
“<span title=’删除文件’ onclick=’deleteFile(\”” + fileObj.id +
“\”)’ style=’font-size:12px;color:
#4684b2;cursor:pointer;border-bottom:1px solid
#4684b2′>删除</span>”; 
        } 
    } 
 
    /**  
    * 删除选择的文件 www.2cto.com   
    */ 
    function deleteFile(fileId) { 
        var trNode = document.getElementById(“tr_” + fileId); 
        var trParent = trNode.parentNode; 
        trParent.removeChild(trNode); 
    } 
 
    /**  
    * excel校验函数  
    */ 
    function checkExcel(filePath) { 
        var subfix = filePath.substring(filePath.lastIndexOf(“.”) +
1); 
        if (subfix != “xls”) { 
            return false; 
        } 
        return true; 
    } 
    /**  
    * 文件上传时的校验逻辑  
    */ 
    function excelUpload() { 
        var fileCount = 0; 
        var files = document.getElementsByTagName(“INPUT”); 
        for (var i = 0; i < files.length; i++) { 
            if (files[i].type.toLowerCase != ‘file’) continue; 
            if (files[i].errFlag) { 
                alert(“导入的文件只能是xls格式,请重新选择.”); 
                files[i].focus(); 
                return; 
            } 
            if (files[i].value != “”) 
                fileCount++; 
        } 
        if (fileCount < 1) { 
            alert(“请先选择要上传的数据文件!”); 
            return; 
        } 
        document.getElementById(“uploadExcelForm”).submit(); 
    } 
    /**  
    * 添加文件  
    */ 
    function addFile() { 
        ++__FILE_INDEX; 
        var fileId = “file” + __FILE_INDEX; 
        var uploadTable = document.getElementById(“tableUploadFile”) 
        var trElement = uploadTable.insertRow(-1); 
        trElement.id = “tr_” + fileId; 
        var tdElement = trElement.insertCell(-1); 
        tdElement.id = “td_” + fileId; 
        tdElement.innerHTML = “<input type=’file’ name='” + fileId +
“‘ id='” + fileId + “‘ size=’30’
style=’padding-left:5px;width:300px;cursor:pointer;’ >” 
               + “<span id=’span_” + fileId +
“‘></span>” 
               + “<span id=’del_” + fileId +
“‘></span>”; 
    }    
</script> 

无可用的url

此时就需要通过ajax向后台脚本发起请求,后台的node.js响应代码如下

res.set({
            'Content-Type': 'application/octet-stream',
            'Content-Disposition': 'attachment; filename=filename.txt',
            'Content-Length': 1000
});
//file是服务器上的文件的具体路径
fs.createReadStream(file).pipe(res);

响应头设为application/octet-stream,表示传递的数据是二进制流,这是由node.js中流操作所产生的数据类型
Content-Disposition设为attachment会弹出对话框让用户下载,filename是保存的文件名

直接采用send_keys的方式就可以:

 

driver.find_element_by_id('upload_pic').send_keys('E:\\1.jpg')

接下来是后台代码:

注意这种方式上传时,页面上不会显示图片缩略图或者图片路径;并且只能上传一张图片。

[csharp]  //保存上传文件 
        try 
        { 
            for (int i = 0; i < Request.Files.Count; i++) 
            { 
                if (Request.Files[“file” + i] != null) 
                { 
                    HttpPostedFile filePost = Request.Files[“file” +
i]; 
                    string filename = filePost.FileName; 
                    Random rd = new Random(); 
                    filename =
filename.Substring(filename.LastIndexOf(‘\\’) + 1); 
                    string savePath = Server.MapPath(“UpLoadFile/” +
rd.Next() + filename); 
                    filePost.SaveAs(savePath); 
                    UpLoadFile upLoadfile = new UpLoadFile(); 
                    upLoadfile.FileObj = mubiao.Obj_Id; 
                    upLoadfile.FileAddr = savePath; 
                    upLoadfile.FileUpLoadDate = DateTime.Now; 
                    new UpLoadFileBLL().InsertUpLoadFile(upLoadfile); 
                } 
            } 
        } 
        catch (Exception) 
        { 
            PageMessageBoxShow(“文件上传失败!”);             
        } 

对于第二种上传文件的方式,或者说想传多个文件的时候,就必须要采用按钮点击的方式,这种方式有个最大的问题就是当点击上传按钮后,会弹出文件选择框,这个选择框是脱离于浏览器的,因此无法直接使用selenium来操作。
目前网上关于使用按钮上传文件的教程,基本上都是介绍如何使用AutoIt V3。
AutoIt有很多的缺点,一是需要编译成exe文件,会被杀毒软件删除;二是由于写autoit脚本的时候,只能使用文件窗口的名称,chrome和firefox上传文件的窗口名称都不一致,这就导致了兼容性问题。
*chrome选择文件的窗口名称是“打开”,Firefox选择文件的窗口名称是“文件上传”。
因此我们需要寻求新的方式,偶然的情况了解到python有一个专门用来测试Win32程序的库
pywinauto,尝试之后发现pywinauto可以避免兼容性问题,并且由于pywinauto是python的库,因此可以直接用写代码的方式而不用编译成exe再调用了。
首先,我们先下载pywinauto:

 

pip install pywinauto

 

pywinauto操作窗口的方式类似AutoIt,也需要先利用 AutoIt或spy++lite
(关于这两种工具的用法,请自行百度)找到选择文件窗口的class_name,文本框和按钮的class_name。
注意,使用pywinauto的时候依然需要通过selenium先点击“上传/下载”按钮,弹出文件选择框,完整的参考脚本如下:

摘自 天易LoveZLL

from pywinauto import application
from selenium import webdriver

…      # 进入文件上传页面的代码省略

driver.find_element_by_id('upload_pic').click()   # 点击上传/浏览按钮
sleep(2)                      # 需要稍作等待,因为点击上传按钮到文件选择窗口打开会有延迟
app = application.Application()   # 实例化Application
# 这里用的class而没有加窗口title,主要为了保证兼容性
app.connect(class_name='#32770')    #根据class_name找到弹出窗口
app["Dialog"]["Edit1"].TypeKeys("E:\\1.jpg")     # 在输入框中输入值
app["Dialog"]["Button1"].click()                 # 点击打开/保存按钮

/prepre name=code class=javasc…

思路与使用AutoIt的思路一样,
通过selenium中的方式点击上传按钮,
注意这里一定要强制等待,等待时长根据机器具体的配置决定,
在打开的文件选择窗口中输入文件的路径,
E:\1.jpg 就是需要上传的文件,
最后确定即可。

以上代码Windows下比较通用,可以直接使用。
Pywinauto操作的方式比AutoIt更简单方便,可以直接写成函数,在脚本中进行调用。另外由于脚本中没有用到窗口的title,因此保证了浏览器兼容性。
这段代码也可以用在文件下载中,其实下载窗口与上传窗口都是一样的,因此下载也可以使用上面的代码。

注意,
如果是64位的python会提示一个警告信息:“UserWarning: 32-bit application
should be automated using 32-bit Python (you use 64-bit Python)
UserWarning)”,可以忽略。

发表评论

电子邮件地址不会被公开。 必填项已用*标注