@@ -72,11 +72,27 @@ class WBCollectionContent extends Component { | |||
filesize(item[2]), | |||
(<div> | |||
<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" | |||
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>) | |||
] | |||
)) | |||
@@ -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'; | |||
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 proxy; | |||
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 = []; | |||
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 url = window.URL.createObjectURL(blob); | |||
const a = document.createElement('a'); | |||
a.href = url; | |||
a.download = name; | |||
a.click(); | |||
}); */ | |||
}); | |||
return prom; | |||
} | |||
export default wbDownloadFile; |