6
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Safariのinput type="file"で問題が繰り返し起きるときの対応

Last updated at Posted at 2019-05-21

はじめに

ファイルアップロードは、かなり鉄板機能なので実装することが多いのですが、ハマりかけたのでログに残しておきます。

エラーまでの経緯

ファイルアップロードのソースは、雰囲気こんな感じです。

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さんは違ったようです。

めでたし。

参考記事

Safari input='file' doesn't work

6
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?