Skip to content

Commit 5f0c75b

Browse files
committed
Get uploading file-path, instead of file, working on Electron.
1 parent e8b6057 commit 5f0c75b

File tree

2 files changed

+89
-42
lines changed

2 files changed

+89
-42
lines changed

js/InterSpec.js

Lines changed: 43 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -111,17 +111,14 @@ function()
111111
xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
112112
xhr.setRequestHeader("X-File-Name", file.name);
113113

114+
114115
//#if( BUILD_AS_ELECTRON_APP ) //C++ preprocessors dont look to work here...
115-
if( lookForPath && file.path && !file.path.toLowerCase().includes('fake') ) {
116+
if( lookForPath && (typeof file.path === "string") && (file.path.length > 2) && !file.path.toLowerCase().includes('fake') ) {
116117
// For Electron builds, file.path gives the full path (including filename), so we
117118
// will just upload the path so we can read it in the c++ to avoid lots of copying and
118119
// stuff. But we also need to fallback, JIC c++ fails for some unforeseen reason.
119120
// See #FileDragUploadResource::handleRequest for the other part of this logic
120-
xhr.setRequestHeader("FullFilePath", file.path);
121-
122-
123-
// TUESDAY TODO: test this for non ASCII paths
124-
// TUESDAY TODO: explicitly trigger a resize event after maximizing window, or putting it back
121+
xhr.setRequestHeader("Is-File-Path", "1" );
125122

126123
console.log( 'Will send file path, instead of actual file; path: ', file.path );
127124

@@ -132,13 +129,14 @@ function()
132129
console.log( 'Failed to upload via Electron path.' );
133130
uploadFileToUrl( uploadURL, file, false );
134131
}else if( xhr.readyState === 4 ) {
135-
console.log( 'Successfully uploaded path.' );
132+
console.log( 'Successfully uploaded path to Electron.' );
136133
}
137134
};
138135

139136
xhr.onloadend = removeUploading;
140-
141-
xhr.send();
137+
138+
const body = JSON.stringify( { fullpath: file.path} );
139+
xhr.send(body);
142140
return;
143141
}//if( have full path on Electron build )
144142
//#endif
@@ -160,8 +158,7 @@ function()
160158
let lastUpdateTime = 0;
161159
xhr.upload.addEventListener('progress', function(pe) {
162160
if(pe.lengthComputable) {
163-
console.log( 'pe.total=' + pe.total + ', pe.loaded=' + pe.loaded );
164-
161+
//console.log( 'pe.total=' + pe.total + ', pe.loaded=' + pe.loaded );
165162
const currentTime = Date.now();
166163
if( (currentTime - lastUpdateTime) > 500 ){
167164
lastUpdateTime = currentTime;
@@ -176,12 +173,37 @@ function()
176173
xhr.addEventListener('abort', removeUploading);
177174
xhr.upload.addEventListener("abort", removeUploading);
178175

179-
xhr.onloadend = removeUploading;
176+
// The loadend event is fired when a request has completed, whether successfully (after
177+
// load) or unsuccessfully (after abort or error).
178+
// If server does not send response, then this function will not be called until
179+
// xhr.timeout/xhr.ontimeout get triggered.
180+
xhr.addEventListener('loadend', function() {
181+
console.log( 'onloadend called: ' + ', readyState=' + xhr.readyState
182+
+ ', status=' + status + ', responseTxt=' + xhr.responseText );
183+
removeUploading();
184+
} );//
185+
186+
187+
// This next function will be called once data is sent to server, but the server doesnt
188+
// have to send the repsonce.
189+
xhr.upload.addEventListener('loadend', function() {
190+
console.log( 'xhr.upload.loadend called' );
191+
removeUploading();
192+
});
193+
194+
195+
/* Lets set a 1-minute timeout so we will eventually remove the uploading cover...
196+
197+
TODO: What we should really do is setup a timeout that fires if 'progress' is never never
198+
called with an appropriate status, and then once it does get called set another timer
199+
as upload is finished, to get the response. I.e., get rid of xhr.ontimeout.
200+
*/
201+
xhr.timeout = 60000;
202+
xhr.ontimeout = function () {
203+
console.error("The request to upload file timed out.");
204+
removeUploading();
205+
};
180206

181-
//xhr.timeout = 5000;
182-
//xhr.ontimeout = function () {
183-
// console.error("The request to upload file timed out.");
184-
//};
185207

186208
xhr.send(file);
187209
};//uploadFileToUrl
@@ -503,6 +525,10 @@ function(resizerid,elid) {
503525
return false;
504526
}
505527

506-
$('#' + resizerid).bind('mousedown.FlexResize touchstart.FlexResize', handleMouseDown);
528+
// Remove the bindings first, JIC this is a duplicate call to initialize the events
529+
// (it doesnt look like this happens, but current code to show/hide tool-tabs is pretty
530+
// fragile, so the off is really just to make sure).
531+
$('#' + resizerid).off('mousedown.FlexResize touchstart.FlexResize')
532+
.on('mousedown.FlexResize touchstart.FlexResize', handleMouseDown);
507533
}
508534
);

src/FileDragUploadResource.cpp

Lines changed: 46 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,11 @@
3131
#include <iostream>
3232
#include <iterator>
3333

34-
34+
#include <Wt/Utils>
3535
#include <Wt/WResource>
36+
#include <Wt/Json/Value>
37+
#include <Wt/Json/Parser>
38+
#include <Wt/Json/Object>
3639
#include <Wt/WJavaScript>
3740
#include <Wt/WApplication>
3841
#include <Wt/WPaintDevice>
@@ -43,6 +46,7 @@
4346
#include <Wt/WCssDecorationStyle>
4447
#include <Wt/Chart/WAbstractChart>
4548

49+
4650
#include "InterSpec/InterSpecApp.h"
4751
#include "SpecUtils/Filesystem.h"
4852
#if( !ANDROID && !IOS )
@@ -123,45 +127,62 @@ void FileDragUploadResource::handleRequest( const Http::Request& request,
123127
return;
124128
}//if( request.tooLarge() )
125129

130+
auto app = WApplication::instance();
131+
if( !app || !m_fileDrop )
132+
{
133+
cerr << "Uploaded file to a non Wt-Sesssion - bailing" << endl;
134+
response.setStatus( 403 ); //Forbidden
135+
return;
136+
}//if( !app )
137+
138+
126139
#if( BUILD_AS_ELECTRON_APP )
127140
// See FileUploadFcn in InterSpec.js
128-
const string fullpath = request.headerValue("FullFilePath");
129-
if( !fullpath.empty() )
141+
const string isFilePath = request.headerValue("Is-File-Path");
142+
143+
if( (isFilePath == "1") || (isFilePath == "true") || (isFilePath == "yes") )
130144
{
131-
bool canRead = false;
132-
133-
{// begin test if can read file
145+
try
146+
{
147+
std::istreambuf_iterator<char> eos;
148+
string body(std::istreambuf_iterator<char>(request.in()), eos);
149+
150+
Json::Object result;
151+
Json::parse( body, result );
152+
if( !result.contains("fullpath") )
153+
throw std::runtime_error( "Body JSON did not contain a 'fullpath' entry." );
154+
155+
const std::string fullpath = result.get("fullpath").toUTF8();
156+
157+
{// begin test if can read file
134158
#ifdef _WIN32
135-
const std::wstring wname = SpecUtils::convert_from_utf8_to_utf16( fullpath );
136-
std::ifstream file( wname.c_str() );
159+
const std::wstring wname = SpecUtils::convert_from_utf8_to_utf16( fullpath );
160+
std::ifstream file( wname.c_str() );
137161
#else
138-
std::ifstream file( fullpath.c_str() );
162+
std::ifstream file( fullpath.c_str() );
139163
#endif
140-
canRead = file.good();
141-
}// end test if can read file
142-
143-
144-
if( canRead ) // if( SpecUtils::is_file(fullpath) )
145-
{
146-
cout << "Got upload of fullpath='" << fullpath << "'" << endl;
164+
if( !file.good() )
165+
throw std::runtime_error( "Could not read '" + fullpath + "'" );
166+
}// end test if can read file
147167

148-
auto app = WApplication::instance();
149-
WApplication::UpdateLock lock( app );
168+
cout << "Will open spectrum file using path='" << fullpath << "'" << endl;
150169

151-
if( m_fileDrop )
152-
m_fileDrop->emit( SpecUtils::filename(fullpath), fullpath );
170+
WApplication::UpdateLock lock( app );
171+
172+
m_fileDrop->emit( SpecUtils::filename(fullpath), fullpath );
153173

154174
app->triggerUpdate();
155-
}else
175+
}catch( std::exception &e )
156176
{
177+
cerr << "Failed to parse fullpath POST request: " << e.what() << " - returning status 406.\n";
178+
157179
response.setStatus( 406 );
158-
output << "Couldnt access filepath";
159180
return;
160-
}
181+
}//try / catch to figure out how to interpret
161182

162183
return;
163-
}//if( !fullpath.empty() )
164-
#endif
184+
}//if( (fullpath == "1") || (fullpath == "true") || (fullpath == "yes") )
185+
#endif //BUILD_AS_ELECTRON_APP
165186

166187
const int datalen = request.contentLength();
167188

0 commit comments

Comments
 (0)