function* uploadImage({ payload: { file, dataUrl, filename = 'image.txt', progress }, }) { const _progress = progress; progress = msg => { // console.log('Upload image progress', msg) _progress(msg); }; const stateUser = yield select(state => state.user); const username = stateUser.getIn(['current', 'username']); const d = stateUser.getIn(['current', 'private_keys', 'posting_private']); if (!username) { progress({ error: 'Please login first.' }); return; } if (!d) { progress({ error: 'Login with your posting key' }); return; } if (!file && !dataUrl) { console.error('uploadImage required: file or dataUrl'); return; } let data, dataBs64; if (file) { // drag and drop const reader = new FileReader(); data = yield new Promise(resolve => { reader.addEventListener('load', () => { const result = new Buffer(reader.result, 'binary'); resolve(result); }); reader.readAsBinaryString(file); }); } else { // recover from preview const commaIdx = dataUrl.indexOf(','); dataBs64 = dataUrl.substring(commaIdx + 1); data = new Buffer(dataBs64, 'base64'); } // The challenge needs to be prefixed with a constant (both on the server and checked on the client) to make sure the server can't easily make the client sign a transaction doing something else. const prefix = new Buffer('ImageSigningChallenge'); const bufSha = hash.sha256(Buffer.concat([prefix, data])); const formData = new FormData(); if (file) { formData.append('file', file); } else { // formData.append('file', file, filename) <- Failed to add filename=xxx to Content-Disposition // Can't easily make this look like a file so this relies on the server supporting: filename and filebinary formData.append('filename', filename); formData.append('filebase64', dataBs64); } const sig = Signature.signBufferSha256(bufSha, d); const postUrl = `${$STM_Config.upload_image}/${username}/${sig.toHex()}`; const xhr = new XMLHttpRequest(); xhr.open('POST', postUrl); xhr.onload = function() { console.log(xhr.status, xhr.responseText); const res = JSON.parse(xhr.responseText); const { error } = res; if (error) { progress({ error: 'Error: ' + error }); return; } const { url } = res; progress({ url }); }; xhr.onerror = function(error) { console.error(filename, error); progress({ error: 'Unable to contact the server.' }); }; xhr.upload.onprogress = function(event) { if (event.lengthComputable) { const percent = Math.round(event.loaded / event.total * 100); progress({ message: `Uploading ${percent}%` }); // console.log('Upload', percent) } }; xhr.send(formData); }
const sign = (role, d) => { if (!d) return; const sig = Signature.signBufferSha256(bufSha, d); signatures[role] = sig.toHex(); };