Closed viiiprock closed 6 years ago
You have a few options. The naive approach would be to trust the client, and have mutation variables accompanying the one holding the file for width, height, etc. A better approach would be to inspect the actual file uploaded in the resolvers.
Depending what sort of file properties you are attempting to inspect, you might be able to read them passively from the stream or you may need to stream the file to a temporary location on the filesystem before looking at it. I don't have any code example handy, but you may have some luck with sharp
metadata
.
thanks @jaydenseric
Sorry to boring you again @jaydenseric I have an issue, but I don't understand where is it come from (front-end of api). So I post my snippets here again.
service
const imgDir = './public/uploads'
mkdirp.sync(imgDir)
const storeFS = ({ stream, filename }) => {
const id = uuid.v4()
const path = `${imgDir}/${id}-${filename}`
return new Promise((resolve, reject) =>
stream
.on('error', error => {
// Delete the truncated file
(error || stream.truncated) && unlinkSync(path)
reject(error)
})
.on('end', () => resolve({ id, path }))
.pipe(createWriteStream(path))
)
}
const processUpload = async upload => {
const { stream, filename, mimetype, encoding } = await upload
const { id, path } = await storeFS({ stream, filename })
return { id, filename, mimetype, encoding, path }
}
resolver
export const uploadImage = async (root, { images }, { mongo: { Images }, user }) => {
const { resolve, reject } = await all(images.map(processUpload))
if (reject.length) {
reject.forEach(({ name, message }) => {
throw new Error(`${name}: ${message}`)
})
}
console.log('RESULT', resolve)
}
create-react-app
starter kitclass Uploader extends React.Component {
handleChange = e => {
e.preventDefault()
const { mutate } = this.props
e.target.validity.valid &&
mutate({
variables: { images: e.target.files }
})
}
render() {
return (
<div>
<input type="file" multiple onChange={this.handleChange}/>
</div>
)
}
}
export default graphql(gql`
mutation($images: [Upload!]!) {
uploadImage(images: $images) {
id
filename
encoding
mimetype
path
}
}
`)(Uploader)
The file upload is success but I got no info inside the file, would you mind to give me a hint to define where issue came from.
note Your example works well
Did the original file have that metadata before it was uploaded?
yes @jaydenseric , your example works well. btw, i used Express, not Koa
@viiiprock : can you use shasum
from the command line to checksum of both files? I tried to run apollo-upload-examples
and metadata still existing after uploaded.
PS: use mdls
to show metadata of the file.
The example works fine, I've used FileReader()
to read width
, height
info on client, so I guessed that it missed something somewhere on the server side, so I'm trying to step by step reproduce from the resolver :D
mdls
might help, thanks @giautm
@giautm This is really weird, I can't image what happened, if I copied the uploaded file to other location, the info existed again.
@viiiprock : Ya, the first time I upload files to the server side, metadata does not exist if I use Get File Info on the uploaded file. Maybe this issues related to Finder on Mac OS.
See this Hacker News post and comment.
Apparently macOS puts "extended attributes" (xattrs) on files, and these can differ between OS versions. Apparently they often get lost when making certain types of transfers.
incredible, seems it make sense now.
For who has same issue Just put repo at Users
(desktop, document...) instead of Volumes
directory.
Hi @jaydenseric How I could attach file info together to the uploaded file such as image dimensions ?