@@ -37,10 +37,10 @@ export class ServerAPI extends APIInterface {
37
37
38
38
subscribeToFilenameChanges ( handler , cancelSignal ) {
39
39
// We need something to hold the one currently active websocket.
40
- subscription = { } ;
40
+ let subscription = { } ;
41
41
42
42
// We make a function to connect the websocket, which we can call to reconnect.
43
- function connect ( ) {
43
+ let connect = ( ) => {
44
44
subscription . ws = new WebSocket ( this . apiUrl . replace ( / ^ h t t p / , "ws" ) ) ;
45
45
subscription . ws . onmessage = ( message ) => {
46
46
if ( ! cancelSignal . aborted ) {
@@ -70,6 +70,66 @@ export class ServerAPI extends APIInterface {
70
70
return subscription ;
71
71
}
72
72
73
+ async putFile ( fileType , file , cancelSignal ) {
74
+
75
+ // Prepare the form data for upload
76
+ const formData = new FormData ( ) ;
77
+ // If the file is anything other than a Blob, it will be turned into a
78
+ // string and added as a normal form value. If it is a Blob it will
79
+ // become a file upload. Note that a File is a kind of Blob. See
80
+ // <https://developer.mozilla.org/en-US/docs/Web/API/FormData/append#value>
81
+ //
82
+ // But in jsdom in the test environment there are two Blob types: Node's
83
+ // and jdsom's, and only jsdom's will work. Node's will turn into a
84
+ // string. And it seems hard to get at both types in a way that makes
85
+ // sense in a browser. So we will add the file and make sure it added OK
86
+ // and didn't stringify.
87
+
88
+ // According to <https://stackoverflow.com/a/43914175>, we *must* set a filename for uploads.
89
+ // In jsdom it turns on jsdom's own type checking support.
90
+ let fileName = file . name || "upload.dat" ;
91
+ formData . append ( "trackFile" , file , fileName ) ;
92
+ if ( typeof formData . get ( "trackFile" ) == "string" ) {
93
+ // Catch stringification in case jsdom didn't.
94
+ console . error (
95
+ "Cannot upload file because it is not the appropriate type:" ,
96
+ file
97
+ ) ;
98
+ throw new Error ( "File is not an appropriate type to upload" ) ;
99
+ }
100
+ // Make sure server can identify a Read file
101
+ formData . append ( "fileType" , fileType ) ;
102
+
103
+ return new Promise ( ( resolve , reject ) => {
104
+ const xhr = new XMLHttpRequest ( ) ;
105
+ xhr . responseType = "json" ;
106
+ xhr . onreadystatechange = ( ) => {
107
+ if ( cancelSignal . aborted && xhr . readyState != 0 ) {
108
+ // First time we have noticed we are aborted. Stop the request.
109
+ xhr . abort ( ) ;
110
+ reject ( new Error ( "Upload aborted" ) ) ;
111
+ return
112
+ }
113
+
114
+ if ( xhr . readyState === 4 ) {
115
+ if ( xhr . status === 200 && xhr . response . path ) {
116
+ // Every thing ok, file uploaded, and we got a path.
117
+ resolve ( xhr . response . path ) ;
118
+ } else {
119
+ // Something weird happened.
120
+ reject ( new Error ( "Failed to upload file: status " + xhr . status + " and response: " + xhr . response ) ) ;
121
+ }
122
+ }
123
+ } ;
124
+
125
+ console . log ( "Uploading file" , file ) ;
126
+ console . log ( "Sending form data" , formData ) ;
127
+ console . log ( "Form file is a " + typeof formData . get ( "trackFile" ) ) ;
128
+ xhr . open ( "POST" , `${ this . apiUrl } /trackFileSubmission` , true ) ;
129
+ xhr . send ( formData ) ;
130
+ } ) ;
131
+ }
132
+
73
133
async getBedRegions ( bedFile , cancelSignal ) {
74
134
const json = await fetchAndParse ( `${ this . apiUrl } /getBedRegions` , {
75
135
signal : cancelSignal ,
0 commit comments