元素码农
基础
UML建模
数据结构
算法
设计模式
网络
TCP/IP协议
HTTPS安全机制
WebSocket实时通信
数据库
sqlite
postgresql
clickhouse
后端
rust
go
java
php
mysql
redis
mongodb
etcd
nats
zincsearch
前端
浏览器
javascript
typescript
vue3
react
游戏
unity
unreal
C++
C#
Lua
App
android
ios
flutter
react-native
安全
Web安全
测试
软件测试
自动化测试 - Playwright
人工智能
Python
langChain
langGraph
运维
linux
docker
工具
git
svn
🌞
🌙
目录
▶
入门指南
Playwright安装与配置
环境要求与验证
第一个自动化测试脚本
▶
核心概念
Browser对象详解
Page对象操作指南
Frame与上下文管理
网络请求拦截与Mock
▶
元素定位与操作
CSS选择器实战
XPath高级定位技巧
文本定位与正则匹配
动态元素等待策略
▶
高级操作指南
文件上传下载处理
多标签页与弹窗管理
浏览器上下文隔离
设备模拟与地理定位
▶
测试框架集成
Jest集成配置
Mocha测试报告生成
持续集成CI/CD配置
▶
最佳实践
测试用例组织结构
性能优化策略
跨浏览器测试方案
▶
疑难解答
常见错误代码解析
元素定位失败分析
浏览器启动问题排查
▶
录制功能指南
录制功能基础入门
录制脚本生成与编辑
高级录制配置与技巧
录制脚本调试与优化
发布时间:
2025-03-27 19:14
↑
☰
# 文件上传下载处理 本文将详细介绍如何在Playwright中处理文件上传和下载操作,帮助你实现文件相关的自动化测试场景。 ## 文件上传 ### 1. 基本上传 ```typescript // 单文件上传 await page.getByLabel('选择文件').setInputFiles('path/to/file.jpg'); // 多文件上传 await page.getByLabel('上传文件').setInputFiles([ 'path/to/file1.jpg', 'path/to/file2.pdf' ]); // 使用文件选择器上传 await page.setInputFiles('input[type="file"]', 'path/to/file.jpg'); ``` ### 2. 高级上传 ```typescript // 创建文件对象 const files = [ { name: 'file.txt', mimeType: 'text/plain', buffer: Buffer.from('Hello World') } ]; // 使用文件对象上传 await page.getByLabel('上传').setInputFiles(files); // 拖拽上传 await page.locator('.upload-zone').setInputFiles('path/to/file.jpg'); ``` ## 文件下载 ### 1. 基本下载 ```typescript // 等待下载开始 const downloadPromise = page.waitForEvent('download'); await page.getByText('下载文件').click(); const download = await downloadPromise; // 保存下载文件 await download.saveAs('./downloaded-file.pdf'); // 获取下载路径 const path = await download.path(); console.log('下载路径:', path); ``` ### 2. 高级下载 ```typescript // 自动保存所有下载 page.on('download', async download => { const path = download.suggestedFilename(); await download.saveAs(`./downloads/${path}`); }); // 处理多个下载 const [download1, download2] = await Promise.all([ page.waitForEvent('download'), page.waitForEvent('download'), page.getByText('批量下载').click() ]); ``` ## 文件验证 ### 1. 上传验证 ```typescript // 验证文件大小限制 const maxSize = 5 * 1024 * 1024; // 5MB const file = 'path/to/large-file.jpg'; const stats = require('fs').statSync(file); if (stats.size > maxSize) { console.log('文件超过大小限制'); } else { await page.setInputFiles('input[type="file"]', file); } // 验证文件类型 const allowedTypes = ['image/jpeg', 'image/png', 'application/pdf']; const fileInput = page.locator('input[type="file"]'); await fileInput.setInputFiles(file); const uploadedFile = await fileInput.inputValue(); const fileType = require('file-type').fromFile(uploadedFile); expect(allowedTypes).toContain(fileType.mime); ``` ### 2. 下载验证 ```typescript // 验证下载文件内容 const download = await page.waitForEvent('download'); const path = await download.path(); const content = require('fs').readFileSync(path, 'utf8'); expect(content).toContain('期望的内容'); // 验证下载文件名 expect(download.suggestedFilename()).toBe('expected-file.pdf'); // 验证下载文件类型 const fileType = require('file-type').fromFile(path); expect(fileType.mime).toBe('application/pdf'); ``` ## 最佳实践 ### 1. 上传优化 ```typescript // 创建上传工具函数 async function uploadFile(page, selector, filePath) { try { await page.setInputFiles(selector, filePath); await page.waitForSelector('.upload-success'); } catch (error) { console.error('上传失败:', error); throw error; } } // 处理大文件上传 async function uploadLargeFile(page, filePath) { await page.setInputFiles('input[type="file"]', filePath); await page.waitForSelector('.progress-bar[value="100"]'); } ``` ### 2. 下载优化 ```typescript // 创建下载工具函数 async function downloadFile(page, triggerSelector) { const downloadPromise = page.waitForEvent('download'); await page.click(triggerSelector); const download = await downloadPromise; const fileName = download.suggestedFilename(); await download.saveAs(`./downloads/${fileName}`); return fileName; } // 自动清理下载文件 afterEach(async () => { const fs = require('fs'); const files = fs.readdirSync('./downloads'); for (const file of files) { fs.unlinkSync(`./downloads/${file}`); } }); ``` ## 调试技巧 ### 1. 上传调试 ```typescript // 监听上传事件 page.on('filechooser', async fileChooser => { console.log('文件选择器已打开'); console.log('接受的文件类型:', fileChooser.accept); }); // 打印上传进度 page.on('request', request => { if (request.url().includes('/upload')) { console.log('开始上传文件'); } }); page.on('response', response => { if (response.url().includes('/upload')) { console.log('上传响应状态:', response.status()); } }); ``` ### 2. 下载调试 ```typescript // 监听下载事件 page.on('download', download => { console.log('开始下载文件:', download.suggestedFilename()); }); // 打印下载进度 let downloadBytes = 0; page.on('response', response => { if (response.headers()['content-disposition']) { response.body().then(buffer => { downloadBytes = buffer.length; console.log('下载大小:', downloadBytes); }); } }); ``` ## 常见问题 ### 1. 上传问题 ```typescript // 处理上传超时 try { await page.setInputFiles('input[type="file"]', file, { timeout: 30000 }); } catch (error) { console.error('上传超时:', error); } // 处理上传失败 page.on('response', async response => { if (response.url().includes('/upload') && !response.ok()) { const error = await response.json(); console.error('上传失败:', error); } }); ``` ### 2. 下载问题 ```typescript // 处理下载取消 const download = await page.waitForEvent('download'); if (await download.failure()) { console.error('下载失败:', await download.failure()); } // 处理下载超时 try { const download = await page.waitForEvent('download', { timeout: 30000 }); await download.saveAs('file.pdf'); } catch (error) { console.error('下载超时:', error); } ``` ## 下一步 1. 探索[多标签页与弹窗管理](/article/playwright/advanced/tab-management) 2. 学习[浏览器上下文隔离](/article/playwright/advanced/browser-context) 3. 了解[设备模拟与地理定位](/article/playwright/advanced/device-emulation) ## 参考资料 - [Playwright文件处理](https://playwright.dev/docs/input#upload-files) - [Playwright下载API](https://playwright.dev/docs/downloads) - [文件类型验证](https://www.npmjs.com/package/file-type)