🖼
アップロードした画像の寸法を得る方法
概略
- Image のインスタンスの src にデータを渡し、読み込まれた段階で寸法がわかる
- その前の段階の読み込み方法に二通りの選択がある
- createObjectURL (Blog URL Scheme)
- FileReader (Data URL Scheme)
- 寸法を知りたいだけならどちらでもよい
- createObjectURL の方がややシンプルに書けるなどの利点はある
- 同時にデータも欲しい場合(通常はこっち)は形式が異なるためどちらでもよくはない
- 読み込みと寸法を得る処理を一緒に行おうとしているからややこしくなっているとも思える
- とにかくめんどい
方法1. 寸法を知りたいだけ
<template lang="pug">
.App
input(type="file" @change="change_handle" ref="input_files_el")
</template>
<script>
export default {
methods: {
change_handle() {
const input_file = this.$refs["input_files_el"].files[0]
const image = new Image()
image.addEventListener("load", () => {
console.log(image.naturalWidth) // => 800
console.log(image.naturalHeight) // => 600
URL.revokeObjectURL(image.src) // (寸法だけを知りたいので)破棄する
})
image.src = URL.createObjectURL(input_file)
console.log(image.src) // => blob:http://localhost:8080/231a3dc4-147d-4298-abad-1d9a5e4f530d
},
},
}
</script>
- 常識的に考えて一瞬で取得できてよさそうな情報だけどこんなに書かないといけない
- input タグを参照した時点でわかるようにしてほしい
方法2. Blob URL Scheme にしつつ寸法も知りたい
<template lang="pug">
.App
input(type="file" @change="change_handle" ref="input_files_el")
img(:src="new_image_url")
</template>
<script>
export default {
data() {
new_image_url: null,
},
methods: {
change_handle() {
const input_file = this.$refs["input_files_el"].files[0]
this.new_image_url = URL.createObjectURL(input_file)
console.log(this.new_image_url) // => blob:http://localhost:8080/231a3dc4-147d-4298-abad-1d9a5e4f530d
if (true) {
const image = new Image()
image.addEventListener("load", () => {
console.log(image.naturalWidth) // => 800
console.log(image.naturalHeight) // => 600
})
image.src = this.new_image_url
}
},
},
}
</script>
-
createObjectURL
で読んでいるので Blob URL Scheme になっている - Blob URL Scheme 形式を img タグの src に渡して表示できる
- しかしサーバー側に渡してサーバーから読み込むことはできない(はず)
方法3. Data URL Scheme にしつつ寸法も知りたい
<template lang="pug">
.App
input(type="file" @change="change_handle" ref="input_files_el")
img(:src="new_image_url")
</template>
<script>
export default {
data() {
new_image_url: null,
},
methods: {
change_handle() {
const input_file = this.$refs["input_files_el"].files[0]
const file_reader = new FileReader()
file_reader.addEventListener("load", () => { // load: 成功したときのイベント
console.log(file_reader.result) // => data:image/jpeg;base64,/9j/4AAQSkZJ...
this.new_image_url = file_reader.result
if (true) {
const image = new Image()
image.addEventListener("load", () => {
console.log(image.naturalWidth) // => 800
console.log(image.naturalHeight) // => 600
})
image.src = this.new_image_url
}
}, false)
file_reader.readAsDataURL(input_file)
},
},
}
</script>
- FileReader で読んでいるので Data URL Scheme になっている
- サーバー側に POST すれば読み取れる
- Ruby なら
base64,
の後ろをBase64.decode64
に渡せばバイナリ化できる - データがでかすぎてログが大変なことになりがち
- Ruby なら
参考 🙏
Discussion