LoginSignup
4
2

More than 5 years have passed since last update.

Chrome拡張機能:ダウンロードしたファイルをアップロードする

Last updated at Posted at 2018-05-25

はじめに

やりたいこと

以下の操作を自動化する。

  1. Flickr等で見つけた自由利用可能な画像ファイルをダウンロードする。
  2. アップロードフォームにダウンロードした画像ファイルを指定してアップロードする。

制限事項

  • たとえChrome拡張機能がダウンロードしたものでも、ローカルのファイルにはアクセスできない。
  • アップロードフォームのファイル選択ダイアログをChrome拡張機能から操作できない。

こうした制限から、メモリ上の画像データから送信データを作成し、アップロードフォームを使わずに送信する必要がある。

手順1:画像ファイルのパスを探す

写真共有サイトは、オリジナル画像を直接表示していない。通信量削減のため縮小したものが表示されているので、まずはリンクをたどってオリジナル画像のURLを取得する。(Flickrの場合は、右下のアイコン「Download this photo」にリンクがある。)

その際、画像ファイルが置かれているドメインを確認し、manifest.jsonのpermissionsに追加する。(Flickrの場合は、「https://c1.staticflickr.com/」など。)ワイルドカードが使えないので、連番が降られている場合はすべての番号を追加する必要がある。

手順2:画像ファイルのダウンロード

XMLHttpRequestのresponseTypeblobを指定することで、画像ファイルをバイナリデータとして取得できる。

background.js
const DownloadBlob = (url) => {
  const p = new Promise(resolve => {
    const xhr = new XMLHttpRequest();
    xhr.open('GET', url, true);
    xhr.responseType = 'blob';
    xhr.addEventListener('loadend', () => {resolve(xhr.response);});
    xhr.send();
  });

  return p;
}

const DownloadImage = async (url) => {
  const imageFile = await DownloadBlob(url);
}

手順3:送信データを作成する

フォーム
<body>
  <form>
    <input type="file" name="file" value=""/><br/>
    <input type="text" name="title" value="タイトル"/><br/>
    <input type="hidden" name="session_id" value="123456789"/>
    <input type="submit" name="submit" value="送信"/>
  </form>
</body>
background.js
const formData = new FormData();
formData.append('file', imageFile, 'ファイル名');
formData.append('title', 'タイトル');
formData.append('session_id', '123456789');
formData.append('submit', '送信'); //これはいらないかも。

FormDataオブジェクトを作成し、name属性をキーに値を追加していく。

ファイルを追加する場合は、第三引数にファイル名を指定する。ファイル名はダウンロードしたURLから切り出してもよいが、自由につけることもできる。

上記のsession_idのように、非表示になっている値も漏れなく追加する。

手順4:データを送信する

作成したFormDataオブジェクトをフォームのURLに送信する。cookieを必要とする場合は、XMLHttpRequestのwithCredentialstrueを指定して、フォームを受信してから送信する。

background.js
const GetForm = (url) => {
  const p = new Promise(resolve => {
    const xhr = new XMLHttpRequest();
    xhr.open('Get', url, true);
    xhr.responseType = 'text';
    xhr.withCredentials = true;
    xhr.addEventListener('loadend', () => {resolve(xhr.response);});
    xhr.send();
  });

  return p;
}

const PostForm = (url, formData) => {
  const p = new Promise(resolve => {
    const xhr = new XMLHttpRequest();
    xhr.open('POST', url, true);
    xhr.responseType = 'text';
    xhr.withCredentials = true;
    xhr.addEventListener('loadend', () => {resolve(xhr.response);});
    xhr.send(formData);
  });

  return p;
}

const UploadImage = async (url, formData) => {
  await GetForm (url);
  await PostForm (url, formData);
}

注意

フォームデータを自作するため、アップロードフォームに備わっているバリデーションチェックが行われない。送信前にフォームデータの整合性を確認する必要がある。

4
2
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
4
2