From 487fbf303571a22fbb2ad80111c8e4a6c0eefd8b Mon Sep 17 00:00:00 2001 From: Jon Leighton Date: Sun, 9 Dec 2012 10:52:52 +0000 Subject: [PATCH] Enable multiple files to be uploaded to a file input Obviously, the input must have the multiple attribute for this to work. The API is: page.uploadFile('#file_input', ['file1', file2']) I haven't implemented support for multiple files in the page.filePicker API because I couldn't work out how to get a return value of an array of strings through the JS/C++ bridge. https://code.google.com/p/phantomjs/issues/detail?id=256 --- src/modules/webpage.js | 13 +++++++++++++ src/webpage.cpp | 10 +++++----- src/webpage.h | 2 +- test/webpage-spec.js | 15 ++++++++++++++- 4 files changed, 33 insertions(+), 7 deletions(-) diff --git a/src/modules/webpage.js b/src/modules/webpage.js index b12bb320..3ff2380a 100644 --- a/src/modules/webpage.js +++ b/src/modules/webpage.js @@ -432,6 +432,19 @@ function decorateNewPage(opts, page) { this.setCookies(cookies); }); + /** + * upload a file + * @param {string} selector css selector for the file input element + * @param {string,array} fileNames the name(s) of the file(s) to upload + */ + page.uploadFile = function(selector, fileNames) { + if (typeof fileNames == "string") { + fileNames = [fileNames]; + } + + this._uploadFile(selector, fileNames); + }; + // Copy options into page if (opts) { page = copyInto(page, opts); diff --git a/src/webpage.cpp b/src/webpage.cpp index ec1bfcfe..7a493c72 100644 --- a/src/webpage.cpp +++ b/src/webpage.cpp @@ -93,7 +93,7 @@ public: Q_UNUSED(option); if (extension == ChooseMultipleFilesExtension) { - static_cast(output)->fileNames = QStringList(m_uploadFile); + static_cast(output)->fileNames = m_uploadFiles; return true; } else { return false; @@ -115,7 +115,7 @@ protected: Q_UNUSED(originatingFrame); QString filePath = m_webPage->filePicker(oldFile); - QString choosenFile = !filePath.isNull() ? filePath : m_uploadFile; + QString choosenFile = !filePath.isNull() ? filePath : m_uploadFiles.first(); // Return the value coming from the "filePicker" callback, IFF not null. qDebug() << "CustomPage - file choosen for upload:" << choosenFile; @@ -213,7 +213,7 @@ protected: private: WebPage *m_webPage; QString m_userAgent; - QString m_uploadFile; + QStringList m_uploadFiles; friend class WebPage; }; @@ -1105,13 +1105,13 @@ QString WebPage::footer(int page, int numPages) return getHeaderFooter(m_paperSize, "footer", m_mainFrame, page, numPages); } -void WebPage::uploadFile(const QString &selector, const QString &fileName) +void WebPage::_uploadFile(const QString &selector, const QStringList &fileNames) { QWebElement el = m_currentFrame->findFirstElement(selector); if (el.isNull()) return; - m_customWebPage->m_uploadFile = fileName; + m_customWebPage->m_uploadFiles = fileNames; el.evaluateJavaScript(JS_ELEMENT_CLICK); } diff --git a/src/webpage.h b/src/webpage.h index e9cb406a..c8176f8b 100644 --- a/src/webpage.h +++ b/src/webpage.h @@ -255,7 +255,7 @@ public slots: QObject *_getFilePickerCallback(); QObject *_getJsConfirmCallback(); QObject *_getJsPromptCallback(); - void uploadFile(const QString &selector, const QString &fileName); + void _uploadFile(const QString &selector, const QStringList &fileNames); void sendEvent(const QString &type, const QVariant &arg1 = QVariant(), const QVariant &arg2 = QVariant(), const QString &mouseButton = QString(), const QVariant &modifierArg = QVariant()); /** diff --git a/test/webpage-spec.js b/test/webpage-spec.js index f614461f..ef36bb7b 100644 --- a/test/webpage-spec.js +++ b/test/webpage-spec.js @@ -476,9 +476,11 @@ describe("WebPage object", function() { it("should handle file uploads", function() { runs(function() { page.content = '\n' + - ''; + '\n' + + ''; page.uploadFile("#file", 'README.md'); page.uploadFile("#file2", 'README.md'); + page.uploadFile("#file3", ['README.md', 'LICENSE.BSD']); }); waits(50); @@ -495,6 +497,17 @@ describe("WebPage object", function() { return document.getElementById('file2').files[0].fileName; }); expect(fileName).toEqual('README.md'); + + var files = page.evaluate(function() { + var files = document.getElementById('file3').files; + return { + length: files.length, + fileNames: [files[0].fileName, files[1].fileName] + } + }); + expect(files.length).toEqual(2) + expect(files.fileNames[0]).toEqual('README.md'); + expect(files.fileNames[1]).toEqual('LICENSE.BSD'); }); });