@@ -37,10 +37,10 @@ export class ServerAPI extends APIInterface {
3737
3838 subscribeToFilenameChanges ( handler , cancelSignal ) {
3939 // We need something to hold the one currently active websocket.
40- subscription = { } ;
40+ let subscription = { } ;
4141
4242 // We make a function to connect the websocket, which we can call to reconnect.
43- function connect ( ) {
43+ let connect = ( ) => {
4444 subscription . ws = new WebSocket ( this . apiUrl . replace ( / ^ h t t p / , "ws" ) ) ;
4545 subscription . ws . onmessage = ( message ) => {
4646 if ( ! cancelSignal . aborted ) {
@@ -70,6 +70,66 @@ export class ServerAPI extends APIInterface {
7070 return subscription ;
7171 }
7272
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+
73133 async getBedRegions ( bedFile , cancelSignal ) {
74134 const json = await fetchAndParse ( `${ this . apiUrl } /getBedRegions` , {
75135 signal : cancelSignal ,
0 commit comments