@@ -72,11 +72,27 @@ class WBCollectionContent extends Component { | |||||
filesize(item[2]), | filesize(item[2]), | ||||
(<div> | (<div> | ||||
<button class="btn btn-outline-primary mx-1" title="Download" | <button class="btn btn-outline-primary mx-1" title="Download" | ||||
onclick={ () => wbDownloadFile(arvHost, arvToken, manifestReader, | |||||
'.' + collectionPath + '/' + item[1]) }><i class="fas fa-download"></i></button> | |||||
onclick={ () => { | |||||
let prom = wbDownloadFile(arvHost, arvToken, manifestReader, | |||||
'.' + collectionPath + '/' + item[1]); | |||||
prom = prom.then(blocks => { | |||||
const blob = new Blob(blocks); | |||||
const a = document.createElement('a'); | |||||
a.name = item[1]; | |||||
a.href = window.URL.createObjectURL(blob); | |||||
a.click(); | |||||
}); | |||||
} }><i class="fas fa-download"></i></button> | |||||
<button class="btn btn-outline-primary mx-1" title="View" | <button class="btn btn-outline-primary mx-1" title="View" | ||||
onclick={ () => wbDownloadFile(arvHost, arvToken, manifestReader, | |||||
'.' + collectionPath + '/' + item[1]) }><i class="far fa-eye"></i></button> | |||||
onclick={ () => { | |||||
let prom = wbDownloadFile(arvHost, arvToken, manifestReader, | |||||
'.' + collectionPath + '/' + item[1]); | |||||
prom = prom.then(blocks => { | |||||
const blob = new Blob(blocks); | |||||
window.open(window.URL.createObjectURL(blob)); | |||||
}); | |||||
} }><i class="far fa-eye"></i></button> | |||||
</div>) | </div>) | ||||
] | ] | ||||
)) | )) | ||||
@@ -0,0 +1,65 @@ | |||||
import makeArvadosRequest from 'make-arvados-request'; | |||||
function rdvHash(serviceId, locator) { | |||||
let blockHash = /^[0-9a-f]{32}/.exec(locator); | |||||
if (!blockHash) | |||||
throw Error('Invalid locator'); | |||||
if (typeof(serviceId) !== 'string') | |||||
throw Error('Invalid service ID'); | |||||
let res = CryptoJS.MD5(serviceId + blockHash).toString(); | |||||
return res; | |||||
} | |||||
function wbDownloadFile(arvHost, arvToken, | |||||
manifestReader, path) { | |||||
const file = manifestReader.getFile(path); | |||||
const name = path.split('/').reverse()[0]; | |||||
const blockRefs = file[0]; | |||||
let services; | |||||
let prom = makeArvadosRequest(arvHost, arvToken, | |||||
'/arvados/v1/keep_services/accessible'); | |||||
prom = prom.then(xhr => (services = xhr.response['items'])); | |||||
const blocks = []; | |||||
for (let i = 0; i < blockRefs.length; i++) { | |||||
prom = prom.then(() => { | |||||
const [ locator, position, size ] = blockRefs[i]; | |||||
const weights = services.map(s => rdvHash(s['uuid'], locator)); | |||||
const order = Object.keys(services).sort((a, b) => weights[b].localeCompare(weights[a])); | |||||
const orderedServices = order.map(i => services[i]); | |||||
let k = 0; | |||||
const cb = () => { | |||||
if (k >= orderedServices.length) | |||||
throw Error('Block not found'); | |||||
const svc = orderedServices[k]; | |||||
k++; | |||||
let prom_1 = makeArvadosRequest(svc.service_host + | |||||
':' + svc.service_port, arvToken, | |||||
'/' + locator, { 'useSsl': svc.service_ssl_flag, | |||||
'responseType': 'arraybuffer' }); | |||||
//prom_1 = prom_1.then(xhr => xhr.response); | |||||
prom_1 = prom_1.catch(cb); | |||||
return prom_1; | |||||
}; | |||||
return cb().then(xhr => (blocks.append(xhr.response.slice(position, size)))); | |||||
}); | |||||
} | |||||
prom = prom.then(() => { | |||||
const blob = new Blob(blocks); | |||||
const url = window.URL.createObjectURL(blob); | |||||
const a = document.createElement('a'); | |||||
a.href = url; | |||||
a.download = name; | |||||
}); | |||||
} | |||||
export default wbDownloadFile; |
@@ -1,65 +1,50 @@ | |||||
import makeArvadosRequest from 'make-arvados-request'; | import makeArvadosRequest from 'make-arvados-request'; | ||||
function rdvHash(serviceId, locator) { | |||||
let blockHash = /^[0-9a-f]{32}/.exec(locator); | |||||
if (!blockHash) | |||||
throw Error('Invalid locator'); | |||||
if (typeof(serviceId) !== 'string') | |||||
throw Error('Invalid service ID'); | |||||
let res = CryptoJS.MD5(serviceId + blockHash).toString(); | |||||
return res; | |||||
} | |||||
function wbDownloadFile(arvHost, arvToken, | function wbDownloadFile(arvHost, arvToken, | ||||
manifestReader, path) { | manifestReader, path) { | ||||
const file = manifestReader.getFile(path); | const file = manifestReader.getFile(path); | ||||
const name = path.split('/').reverse()[0]; | const name = path.split('/').reverse()[0]; | ||||
const blockRefs = file[0]; | const blockRefs = file[0]; | ||||
let services; | |||||
let proxy; | |||||
let prom = makeArvadosRequest(arvHost, arvToken, | let prom = makeArvadosRequest(arvHost, arvToken, | ||||
'/arvados/v1/keep_services/accessible'); | |||||
prom = prom.then(xhr => (services = xhr.response['items'])); | |||||
'/arvados/v1/keep_services'); | |||||
prom = prom.then(xhr => { | |||||
const services = xhr.response['items']; | |||||
const proxies = services.filter(svc => (svc.service_type === 'proxy')); | |||||
const n = Math.floor(Math.random() * proxies.length); | |||||
proxy = proxies[n]; | |||||
}); | |||||
const blocks = []; | const blocks = []; | ||||
for (let i = 0; i < blockRefs.length; i++) { | for (let i = 0; i < blockRefs.length; i++) { | ||||
prom = prom.then(() => { | |||||
const [ locator, position, size ] = blockRefs[i]; | |||||
const weights = services.map(s => rdvHash(s['uuid'], locator)); | |||||
const order = Object.keys(services).sort((a, b) => weights[b].localeCompare(weights[a])); | |||||
const orderedServices = order.map(i => services[i]); | |||||
let k = 0; | |||||
const cb = () => { | |||||
if (k >= orderedServices.length) | |||||
throw Error('Block not found'); | |||||
const svc = orderedServices[k]; | |||||
k++; | |||||
let prom_1 = makeArvadosRequest(svc.service_host + | |||||
':' + svc.service_port, arvToken, | |||||
'/' + locator, { 'useSsl': svc.service_ssl_flag, | |||||
'responseType': 'arraybuffer' }); | |||||
//prom_1 = prom_1.then(xhr => xhr.response); | |||||
prom_1 = prom_1.catch(cb); | |||||
return prom_1; | |||||
}; | |||||
return cb().then(xhr => (blocks.append(xhr.response.slice(position, size)))); | |||||
}); | |||||
const [ locator, position, size ] = blockRefs[i]; | |||||
prom = prom.then(() => makeArvadosRequest( | |||||
proxy.service_host + ':' + proxy.service_port, | |||||
arvToken, | |||||
'/' + locator, | |||||
{ 'useSsl': proxy.service_ssl_flag, | |||||
'responseType': 'arraybuffer' } | |||||
)); | |||||
prom = prom.then(xhr => (blocks.push(xhr.response.slice(position, | |||||
position + size)))); | |||||
} | } | ||||
prom = prom.then(() => { | |||||
prom = prom.then(() => blocks); | |||||
/* prom = prom.then(() => { | |||||
const blob = new Blob(blocks); | const blob = new Blob(blocks); | ||||
const url = window.URL.createObjectURL(blob); | const url = window.URL.createObjectURL(blob); | ||||
const a = document.createElement('a'); | const a = document.createElement('a'); | ||||
a.href = url; | a.href = url; | ||||
a.download = name; | a.download = name; | ||||
a.click(); | |||||
}); */ | |||||
}); | |||||
return prom; | |||||
} | } | ||||
export default wbDownloadFile; | export default wbDownloadFile; |