Last active
May 31, 2017 22:57
-
-
Save macrozone/b2207c19aed0838d5982a09a5399dcae to your computer and use it in GitHub Desktop.
File-filed with uniforms and ostrio:files in meteor
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from 'react'; | |
import { connectField } from 'uniforms'; | |
import Dropzone from 'react-dropzone'; | |
import withMeteorUploader from '../../hocs/with_meteor_uploader'; | |
import CollectionImage from '/client/modules/core/containers/collection_image'; | |
export const ImageFile = ({ | |
disabled, | |
id, | |
label, | |
uploadFile, | |
uploadProgress, | |
uploadState, | |
uploadError, | |
name, | |
onChange, | |
placeholder, | |
hintText, | |
hintTitle, | |
value, | |
...props, | |
}) => { | |
const onDrop = (files) => { | |
// only take one | |
const file = files[0]; | |
uploadFile(file, (error, file) => { | |
if (error) { | |
console.error(error); | |
} else { | |
onChange(file._id); | |
} | |
}); | |
}; | |
return ( | |
<div> | |
{label && ( | |
<span>{label}</span> | |
)} | |
<div> | |
<Dropzone onDrop={onDrop}> | |
{uploadState === 'uploading' ? | |
<div>Uploading... {uploadProgress}</div> : | |
<div> | |
{value ? <CollectionImage aspectRatio={aspectRatio} imageId={value} /> : null} | |
</div> | |
} | |
</Dropzone> | |
{uploadError ? <p>{uploadError.message}</p> : null} | |
</div> | |
</div> | |
); | |
}); | |
export default connectField(withMeteorUploader(ImageFile)); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Meteor } from 'meteor/meteor'; | |
if (Meteor.isClient) { | |
require('blueimp-canvas-to-blob'); // polyfill | |
} | |
export default (file, { maxDimension = 640, quality = 0.6 } = {}, onResult) => { | |
// thx http://stackoverflow.com/questions/23945494/use-html5-to-resize-an-image-before-upload | |
// Load the image | |
const reader = new global.FileReader(); | |
reader.onload = function (readerEvent) { | |
const image = new global.Image(); | |
image.onload = function (imageEvent) { | |
// Resize the image | |
const canvas = global.document.createElement('canvas'); | |
let width = image.width; | |
let height = image.height; | |
if (width > height) { | |
if (width > maxDimension) { | |
height *= maxDimension / width; | |
width = maxDimension; | |
} | |
} else if (height > maxDimension) { | |
width *= maxDimension / height; | |
height = maxDimension; | |
} | |
canvas.width = width; | |
canvas.height = height; | |
canvas.getContext('2d').drawImage(image, 0, 0, width, height); | |
canvas.toBlob((blob) => { | |
onResult(null, blob); | |
}, 'image/jpeg', quality); | |
}; | |
image.src = readerEvent.target.result; | |
}; | |
reader.readAsDataURL(file); | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { useDeps, composeAll, composeWithTracker, compose } from 'mantra-core'; | |
import { withState } from 'recompose'; | |
import resize from '/manul-files/resize'; | |
import _ from 'lodash'; | |
const RESIZABLE_MIME_TYPES = ['image/jpeg', 'image/png', 'image/gif']; | |
const RESIZE_OPTIONS = { | |
maxDimension: 720, | |
quality: 0.8, | |
}; | |
export const composer = ({ context, imageId, setUploadState, setUploadError, setUploadProgress, directiveName }, onData) => { | |
const { Collections: { Images } } = context(); | |
const shouldResize = ({ size, type }) => { | |
if (Images.MAX_SIZE * 1024 >= size) { | |
return false; | |
} | |
if (_.includes(RESIZABLE_MIME_TYPES, type)) { | |
return true; | |
} | |
return false; | |
}; | |
const upload = (file, onUploadDone) => { | |
const uploader = Images.insert({ | |
file, | |
meta: { directiveName }, | |
streams: 'dynamic', | |
chunkSize: 'dynamic', | |
}, false); | |
uploader.on('progress', (progress) => { | |
setUploadProgress(progress); | |
}); | |
uploader.on('end', (error, result) => { | |
setUploadState(null); | |
setUploadError(error); | |
onUploadDone(error, result); | |
}); | |
uploader.on('start', () => { | |
setUploadState('uploading'); | |
}); | |
uploader.start(); | |
}; | |
const uploadFile = (file, onUploadDone) => { | |
if (shouldResize(file)) { | |
resize(file, RESIZE_OPTIONS, (error, fileResized) => { | |
if (!error) { | |
fileResized.name = file.name + '.jpg'; | |
upload(fileResized, onUploadDone); | |
} else { | |
onUploadDone(error); | |
} | |
}); | |
} else { | |
upload(file, onUploadDone); | |
} | |
}; | |
onData(null, { uploadFile, maxSize: Images.MAX_SIZE }); | |
}; | |
export const depsMapper = (context, actions) => ({ | |
context: () => context, | |
}); | |
export default C => composeAll( | |
compose(composer), | |
withState('uploadError', 'setUploadError', null), | |
withState('uploadProgress', 'setUploadProgress', 0), | |
withState('uploadState', 'setUploadState', null), | |
useDeps(depsMapper) | |
)(C); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
withMeteorUploader is a hoc (higher order component) that injects properties to the wrapped component: