1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

はじめに

GASでPDFなどのファイルのアップロードに対応する
以下のようなアプリを作成します。

image.png

ファイルを選択して、処理開始を押すとアップロードが開始されます。
問題なければ以下の様に表示されます。

image.png

コード

Code.gs
function processFiles(fileObjects) {
  var results = [];
  // ファイル格納先のフォルダのIDを指定
  var folderId = "ここにフォルダのIDを入れます";
  var folder = DriveApp.getFolderById(folderId);

  for (var i = 0; i < fileObjects.length; i++) {
    var file = fileObjects[i];
    var blob = Utilities.newBlob(Utilities.base64Decode(file.data), file.mimeType, file.name);

    var uploadedFile = folder.createFile(blob);
    var fileId = uploadedFile.getId();

    // 処理完了後の表示に使う(要修正)
    results.push({ name: file.name, text: file.name, url: file.name });
  }
  return results;
}
index.html
index.html
<!DOCTYPE html>
<html lang="ja">
<head>
  <base target="_top">
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Web App</title>
  <script src="https://cdn.tailwindcss.com"></script>
  <script src="https://unpkg.com/vue@3/dist/vue.global.prod.js"></script>
</head>
<body class="bg-gray-100 dark:bg-gray-900 text-gray-900 dark:text-gray-100">
  <div id="app" class="container mx-auto px-4 py-8">
    <h1 class="text-3xl font-bold mb-8 text-center">Advanced OCR Web App</h1>
    
    <div class="mb-8">
      <label for="fileUpload" class="block text-lg font-medium mb-2">ファイルをアップロード (PDF, PNG, JPG, JPEG)</label>
      <input type="file" id="fileUpload" ref="fileUpload" @change="handleFileUpload" multiple accept=".pdf,.png,.jpg,.jpeg" class="block w-full text-sm text-gray-500
        file:mr-4 file:py-2 file:px-4
        file:rounded-full file:border-0
        file:text-sm file:font-semibold
        file:bg-blue-50 file:text-blue-700
        hover:file:bg-blue-100
      "/>
    </div>
    
    <button @click="processFiles" :disabled="!files.length || processing" class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded disabled:opacity-50 disabled:cursor-not-allowed">
      処理開始
    </button>
    
    <div v-if="processing" class="mt-4">
      <div class="w-full bg-gray-200 rounded-full h-2.5 dark:bg-gray-700">
        <div class="bg-blue-600 h-2.5 rounded-full" :style="{ width: `${progress}%` }"></div>
      </div>
      <p class="text-center mt-2">処理中... {{ progress }}%</p>
    </div>
    
    <div v-if="results.length" class="mt-8">
      <h2 class="text-2xl font-bold mb-4">処理結果</h2>
      <div v-for="(result, index) in results" :key="index" class="mb-4 p-4 bg-white dark:bg-gray-800 rounded shadow">
        <h3 class="text-xl font-semibold mb-2">{{ result.name }}</h3>
        <pre class="whitespace-pre-wrap">{{ result.text }}</pre>
      </div>
    </div>
    
    <div v-if="error" class="mt-4 p-4 bg-red-100 border border-red-400 text-red-700 rounded">
      {{ error }}
    </div>
  </div>

  <script>
    const { createApp, ref, computed } = Vue;
    
    createApp({
      setup() {
        const files = ref([]);
        const results = ref([]);
        const processing = ref(false);
        const progress = ref(0);
        const error = ref('');
        
        const handleFileUpload = (event) => {
          files.value = Array.from(event.target.files);
        };
        
        const processFiles = async () => {
          if (!files.value.length) return;
          
          processing.value = true;
          progress.value = 0;
          results.value = [];
          error.value = '';
          
          const fileObjects = await Promise.all(files.value.map(fileToObject));
          
          try {
            const processedResults = await google.script.run
              .withSuccessHandler((res) => {
                results.value = res;
                processing.value = false;
                progress.value = 100;
              })
              .withFailureHandler((err) => {
                error.value = `エラーが発生しました: ${err.message || err}`;
                processing.value = false;
              })
              .processFiles(fileObjects);
          } catch (err) {
            error.value = `エラーが発生しました: ${err.message || err}`;
            processing.value = false;
          }
        };
        
        const fileToObject = (file) => {
          return new Promise((resolve, reject) => {
            const reader = new FileReader();
            reader.onload = (e) => {
              resolve({
                name: file.name,
                mimeType: file.type,
                data: e.target.result.split(',')[1]
              });
              progress.value += (100 / files.value.length) / 2;
            };
            reader.onerror = (e) => reject(e);
            reader.readAsDataURL(file);
          });
        };
        
        return {
          files,
          results,
          processing,
          progress,
          error,
          handleFileUpload,
          processFiles
        };
      }
    }).mount('#app');
  </script>
</body>
</html>
1
1
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
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?