LoginSignup
11
5

More than 5 years have passed since last update.

GyazoとImgurのapiを使ってストレージを節約 with Vue

Posted at

スクリーンショット (64).png
DEMOページ https://gyazo-imgur.netlify.com/
GitHub https://github.com/ErgoFriend/gyazo-imgur
画像をアップロードしてgyazoもしくはimugrのurlを返してくれます。
書いてる途中にエンコードすればいいのかって思いましたけど、どうなんでしょうかねその辺。

ドキュメント

Gyazo

ドキュメント https://gyazo.com/api?lang=ja
アップロード エンドポイント https://upload.gyazo.com/api/upload

Imgur

ドキュメント https://apidocs.imgur.com/
アプリケーションを作成する https://api.imgur.com/oauth2/addclient
アップロード エンドポイント https://api.imgur.com/3/image

JavaScript

javascriptでapiを利用する

今回はfetchを使用してます。
Gyazoにアップロードする際に、Authorization = 'Client-ID ' + apiKey;をヘッダーに含めてしまうとAccess-Control-Allow-Originエラーが出てしまいまいした。
なので、Vueでは条件分岐させています。

if (this.api.service == 'gyazo') {
  data.append('imagedata', files[0]);
  data.append('access_token', apiKey);
} else {
  data.append('image', files[0]);
  content.headers.Authorization = 'Client-ID ' + apiKey;
}
// https://api.imgur.com/3/image
// https://upload.gyazo.com/api/upload
const apiUrl = '';
// https://imgur.com/account/settings/apps
// https://gyazo.com/oauth/applications
const apiKey = '';

// Common
let data = new FormData();
let content = {
  method: 'POST',
  headers: {
    Accept: 'application/json'
  },
  body: data,
  mimeType: 'multipart/form-data'
};

// Gyazo
data.append('imagedata', files[0]);
data.append('access_token', apiKey);
// Imgur
data.append('image', files[0]);
content.headers.Authorization = 'Client-ID ' + apiKey; // Don't include gyazo api

fetch(apiUrl, content)
  .then(
    response => response.json() // if the response is a JSON object
  )
  .then(success => {
    console.log(success);
    console.log(success.url); // Gyazo API
    console.log(success.data.link); // Imgur API
  })
  .catch(
    error => console.log(error) // Handle the error response object
  );

Vue

環境変数

GyazoとImgurのAPIトークンはtoken: process.env.VUE_APP_GYAZOのように環境変数から読み込んでいます。
環境変数を使うには、プロジェクトルートに.env.localというファイルを作成します。(package.jsonがあるとこ)
変数名の最初にVUE_APP_を付けることでvueから使用できます。

.env.local
VUE_APP_GYAZO='xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
VUE_APP_IMGUR='zzzzzzzzzzzz'

コンポーネント

Uploader.vuepropsapiというオブジェクト変数を作ります。
親コンポーネントから渡した例

App.vue
<template>
  <div id="app">
    <Uploader class="api" :api="gyazo"/>
    <Uploader class="api" :api="imgur"/>
  </div>
</template>
<script>
import Uploader from './components/Uploader.vue';
export default {
  name: 'app',
  components: {
    Uploader
  },
  data() {
    return {
      imgur: {
        service: 'imgur',
        url: 'https://api.imgur.com/3/image',
        token: process.env.VUE_APP_IMGUR,
        logo: 'data:image/jpeg;base64,xxxxxxxxxxxxxxxxxxxxx'
      },
      gyazo: {
        service: 'gyazo',
        url: 'https://upload.gyazo.com/api/upload',
        token: process.env.VUE_APP_GYAZO,
        logo: 'https://i.imgur.com/ylzMVIk.png'
      }
    };
  }
};
</script>
Uploader.vue
<template>
  <div class="api_container">
    <div style="height: 160px;">
      <img :src="api.logo" style="max-width: 300px;"/>
    </div>
    <br>
    <input v-show="!image_url" type="file" id="image_file" @change="onFileChange"  class="imgur" accept="image/*" required/>
    <button v-show="image_url" type="button" @click="removeImage">取り消す</button>
    <br>
    <p>URL: {{ image_url }}</p>
    <br>
    <div style="height: 300px;">
      <img :src="image_thum" id="image_thum" style="max-width: 300px;"/>
    </div>
  </div>
</template>
<script>
export default {
  props: {
    api: {
      type: Object,
      logo: String,
      url: String,
      token: String,
      service: String
    }
  },
  data() {
    return {
      loading_gif:
        'https://cdn-images-1.medium.com/max/1600/1*9EBHIOzhE1XfMYoKz1JcsQ.gif',
      image_thum_sample:
        'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTaE2sVZUD0TFLL7ix68tjo2PG0cgxb_NFR65Thfr_VuC45yGfT',
      image_thum:
        'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTaE2sVZUD0TFLL7ix68tjo2PG0cgxb_NFR65Thfr_VuC45yGfT',
      image_url: null
    };
  },
  methods: {
    onFileChange: function(e) {
      let files = e.target.files || e.dataTransfer.files;
      if (!files.length) {
        return;
      }

      const apiUrl = this.api.url;
      const apiKey = this.api.token;

      this.image_thum = this.loading_gif;
      this.image_url = ' アップロードしています...';

      let data = new FormData();
      let content = {
        method: 'POST',
        headers: {
          //Authorization: 'Client-ID ' + apiKey,
          Accept: 'application/json'
        },
        body: data,
        mimeType: 'multipart/form-data'
      };

      if (this.api.service == 'gyazo') {
        console.debug('gyazo');
        data.append('imagedata', files[0]);
        data.append('access_token', apiKey);
      } else {
        console.debug('imgur');
        data.append('image', files[0]);
        content.headers.Authorization = 'Client-ID ' + apiKey;
      }

      fetch(apiUrl, content)
        .then(
          response => response.json() // if the response is a JSON object
        )
        .then(
          success => {
            console.log(success);
            if (this.api.service == 'gyazo') {
              console.log(success.url);
              this.image_url = success.url;
            } else {
              console.log(success.data.link);
              this.image_url = success.data.link;
            }
            this.createImage(files[0]);
          } // Handle the success response object
        )
        .catch(
          error => console.log(error) // Handle the error response object
        );
    },
    createImage(file) {
      let reader = new FileReader();
      reader.onload = e => {
        this.image_thum = e.target.result;
      };
      reader.readAsDataURL(file);
    },
    removeImage() {
      this.image_url = '';
      document.getElementById('image_file').value = '';
      this.image_thum = this.image_thum_sample;
    }
  }
};
</script>
11
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
11
5