はじめに
ファイルアップロードは、かなり鉄板機能なので実装することが多いのですが、ハマりかけたのでログに残しておきます。
エラーまでの経緯
ファイルアップロードのソースは、雰囲気こんな感じです。
inputタグをそのまま使うとダサいので、style="display: none"にして、その代わりにボタンやフォームのクリックイベントでinputタグのクリックイベントを発火します。
<template>
<!-- 上は省略 -->
<div class="text-xs-center">
<img :src="imageUrl" height="200" v-if="imageUrl"/>
<v-text-field color="primary" label="Select Image" @click='pickFile' v-model='imageName' prepend-icon='attach_file'></v-text-field>
<input
type="file"
style="display: none"
ref="image"
accept="image/*"
@change="onFilePicked"
>
</div>
<!-- 下も省略 -->
</template>
<script>
export default {
data () {
return {
imageName: '',
contentType: '',
imageUrl: '',
imageFile: ''
}
},
methods : {
pickFile () {
this.$refs.image.click ()
},
onFilePicked (e) {
const files = e.target.files
if(files[0] !== undefined) {
this.imageName = files[0].name
this.contentType = files[0].type // contentType: image/jpegとか
if(this.imageName.lastIndexOf('.') <= 0) { return }
const fr = new FileReader ()
fr.readAsDataURL(files[0])
fr.addEventListener('load', () => {
this.imageUrl = fr.result
this.imageFile = files[0] // this is an image file that can be sent to server...
})
} else {
this.imageName = ''
this.imageFile = ''
this.imageUrl = ''
}
}
},
/** いろいろ省略 **/
}
</script>
開発が一段落し、自分のiPhoneでぽちぽちやっていると、こんな現象に遭遇しました。
問題が起きたため、このWebページが再読込されました。
XXXXXXXXで問題が繰り返し起きました。
調べた
Safariでは、display:noneに問題があるらしいです。なので、**『inputタグはdisplay:noneではなく、divで囲んでheightとwidthを0にせよ』**とのことでした。
<template>
<!-- 上は省略 -->
<div class="text-xs-center">
<img :src="imageUrl" height="200" v-if="imageUrl"/>
<v-text-field color="primary" label="Select Image" @click='pickFile' v-model='imageName' prepend-icon='attach_file'></v-text-field>
<div class="hiddenfile"> <!-- ←これで囲む -->
<input
type="file"
ref="image"
accept="image/*"
@change="onFilePicked"
>
</div>
</div>
<!-- 下も省略 -->
</template>
<script>
/** 変更なし **/
</script>
<style scoped>
.hiddenfile {
width: 0px;
height: 0px;
overflow: hidden;
}
</style>
う〜ん何故だろう、、、
むかしからdisplay:noneが常識かつ定石だと思っていましたら、Safariさんは違ったようです。
めでたし。