Google Forms에서 Google Drive에 파일 업로드하기

코딩 수준: 초급
소요 시간: 10분
프로젝트 유형: 이벤트 기반 트리거를 사용한 자동화

목표

  • 솔루션의 작동 방식을 이해합니다.
  • 솔루션 내에서 Apps Script 서비스가 하는 작업을 이해합니다.
  • 스크립트를 설정합니다.
  • 스크립트를 실행합니다.

이 솔루션 정보

Google Forms를 사용하여 Google Drive에 파일을 동시에 업로드하고 정리하세요. 양식에는 업로드할 파일과 파일을 구성하는 방법에 관한 입력이 포함됩니다.

파일 업로드 양식 스크린샷

작동 방식

설정 함수는 업로드한 모든 파일을 저장하는 폴더를 만들고 사용자가 양식을 제출할 때마다 실행되는 트리거를 생성합니다. 사용자가 양식을 작성할 때 업로드할 파일과 파일을 저장할 하위 폴더를 선택합니다. 사용자가 양식을 제출하면 스크립트는 파일을 해당 하위 폴더로 라우팅합니다. 폴더가 아직 없으면 스크립트가 폴더를 만듭니다.

Apps Script 서비스

이 솔루션은 다음 서비스를 사용합니다.

  • 스크립트 서비스: 사용자가 양식을 제출할 때마다 실행되는 트리거를 만듭니다.
  • 속성 서비스: 중복 트리거를 방지하기 위해 설정 중에 스크립트가 만드는 트리거의 ID를 저장합니다.
  • Drive 서비스: 설정 중에 Drive에서 양식의 위치를 가져와 동일한 위치에 폴더를 만듭니다. 사용자가 양식을 제출하면 Drive 서비스는 파일을 해당 폴더로 라우팅하고 선택한 경우 지정된 하위 폴더로 라우팅합니다. 하위 폴더가 아직 없으면 스크립트가 하위 폴더를 만듭니다.
  • 양식 서비스: 사용자가 양식을 제출한 후 선택한 파일 및 폴더 이름을 가져와 Drive 서비스로 전송합니다.

기본 요건

이 샘플을 사용하려면 다음 기본 요건이 필요합니다.

  • Google 계정 (Google Workspace 계정의 경우 관리자 승인이 필요할 수 있음)
  • 인터넷에 액세스할 수 있는 웹브라우저

스크립트 설정

양식 만들기

  1. forms.google.com으로 이동하여 빈 양식 을 클릭합니다.
  2. 제목 없는 양식을 클릭하고 양식의 이름을 Drive에 파일 업로드로 바꿉니다.
  3. 제목 없는 질문을 클릭하고 질문 이름을 하위 폴더로 바꿉니다.
  4. 하위 폴더 질문에서 더보기 > 설명을 클릭합니다.
  5. 설명파일을 저장할 하위 폴더를 선택합니다. <없음>을 선택하면 파일이 업로드된 파일 폴더에 저장됩니다.
  6. 하위 폴더 질문에 다음 옵션을 추가합니다.
    • <없음>
    • 프로젝트 A
    • 프로젝트 B
    • 프로젝트 C
  7. 질문을 필수로 설정하려면 필수를 클릭합니다.
  8. 질문 추가 를 클릭합니다.
  9. 다중 선택을 클릭하고 파일 업로드를 선택합니다.
  10. 계속을 클릭합니다.
  11. 질문업로드할 파일을 입력합니다. 사용자가 업로드할 수 있는 파일 형식과 최대 파일 수를 선택할 수 있습니다.
  12. 질문을 필수로 설정하려면 필수를 클릭합니다.

Apps Script 프로젝트 만들기

  1. 양식에서 더보기 > 스크립트 편집기를 클릭합니다.
  2. 제목 없는 프로젝트를 클릭하고 프로젝트 이름을 Drive에 파일 업로드로 바꿉니다.
  3. 다른 스크립트 파일을 만들려면 파일 추가 > 스크립트를 클릭합니다. 파일 이름을 Setup로 지정합니다.
  4. 두 스크립트 파일의 콘텐츠를 다음 콘텐츠로 바꿉니다.

    Code.gs

    solutions/automations/upload-files/Code.js
    // TODO Before you start using this sample, you must run the setUp() 
    // function in the Setup.gs file.
    
    // Application constants
    const APP_TITLE = "Upload files to Drive from Forms";
    const APP_FOLDER_NAME = "Upload files to Drive (File responses)";
    
    // Identifies the subfolder form item
    const APP_SUBFOLDER_ITEM = "Subfolder";
    const APP_SUBFOLDER_NONE = "<None>";
    
    
    /**
     * Gets the file uploads from a form response and moves files to the corresponding subfolder.
     *  
     * @param {object} event - Form submit.
     */
    function onFormSubmit(e) {
      try {
        // Gets the application root folder.
        var destFolder = getFolder_(APP_FOLDER_NAME);
    
        // Gets all form responses.
        let itemResponses = e.response.getItemResponses();
    
        // Determines the subfolder to route the file to, if any.
        var subFolderName;
        let dest = itemResponses.filter((itemResponse) =>
          itemResponse.getItem().getTitle().toString() === APP_SUBFOLDER_ITEM);
    
        // Gets the destination subfolder name, but ignores if APP_SUBFOLDER_NONE was selected;
        if (dest.length > 0) {
          if (dest[0].getResponse() != APP_SUBFOLDER_NONE) {
            subFolderName = dest[0].getResponse();
          }
        }
        // Gets the subfolder or creates it if it doesn't exist.
        if (subFolderName != undefined) {
          destFolder = getSubFolder_(destFolder, subFolderName)
        }
        console.log(`Destination folder to use:
        Name: ${destFolder.getName()}
        ID: ${destFolder.getId()}
        URL: ${destFolder.getUrl()}`)
    
        // Gets the file upload response as an array to allow for multiple files.
        let fileUploads = itemResponses.filter((itemResponse) => itemResponse.getItem().getType().toString() === "FILE_UPLOAD")
          .map((itemResponse) => itemResponse.getResponse())
          .reduce((a, b) => [...a, ...b], []);
    
        // Moves the files to the destination folder.
        if (fileUploads.length > 0) {
          fileUploads.forEach((fileId) => {
            DriveApp.getFileById(fileId).moveTo(destFolder);
            console.log(`File Copied: ${fileId}`)
          });
        }
      }
      catch (err) {
        console.log(err);
      }
    }
    
    
    /**
     * Returns a Drive folder under the passed in objParentFolder parent
     * folder. Checks if folder of same name exists before creating, returning 
     * the existing folder or the newly created one if not found.
     *
     * @param {object} objParentFolder - Drive folder as an object.
     * @param {string} subFolderName - Name of subfolder to create/return.
     * @return {object} Drive folder
     */
    function getSubFolder_(objParentFolder, subFolderName) {
    
      // Iterates subfolders of parent folder to check if folder already exists.
      const subFolders = objParentFolder.getFolders();
      while (subFolders.hasNext()) {
        let folder = subFolders.next();
    
        // Returns the existing folder if found.
        if (folder.getName() === subFolderName) {
          return folder;
        }
      }
      // Creates a new folder if one doesn't already exist.
      return objParentFolder.createFolder(subFolderName)
        .setDescription(`Created by ${APP_TITLE} application to store uploaded Forms files.`);
    }
    

    Setup.gs

    solutions/automations/upload-files/Setup.js
    // TODO You must run the setUp() function before you start using this sample.
    
    /** 
     * The setUp() function performs the following:
     *  - Creates a Google Drive folder named by the APP_FOLDER_NAME
     *    variable in the Code.gs file.
     *  - Creates a trigger to handle onFormSubmit events.
     */
    function setUp() {
      // Ensures the root destination folder exists.
      const appFolder = getFolder_(APP_FOLDER_NAME);
      if (appFolder !== null) {
        console.log(`Application folder setup.
        Name: ${appFolder.getName()}
        ID: ${appFolder.getId()}
        URL: ${appFolder.getUrl()}`)
      }
      else {
        console.log(`Could not setup application folder.`)
      }
      // Calls the function that creates the Forms onSubmit trigger.
      installTrigger_();
    }
    
    /** 
     * Returns a folder to store uploaded files in the same location
     * in Drive where the form is located. First, it checks if the folder
     * already exists, and creates it if it doesn't.
     *
     * @param {string} folderName - Name of the Drive folder. 
     * @return {object} Google Drive Folder
     */
    function getFolder_(folderName) {
    
      // Gets the Drive folder where the form is located.
      const ssId = FormApp.getActiveForm().getId();
      const parentFolder = DriveApp.getFileById(ssId).getParents().next();
    
      // Iterates through the subfolders to check if folder already exists.
      // The script checks for the folder name specified in the APP_FOLDER_NAME variable.
      const subFolders = parentFolder.getFolders();
      while (subFolders.hasNext()) {
        let folder = subFolders.next();
    
        // Returns the existing folder if found.
        if (folder.getName() === folderName) {
          return folder;
        }
      }
      // Creates a new folder if one doesn't already exist.
      return parentFolder.createFolder(folderName)
        .setDescription(`Created by ${APP_TITLE} application to store uploaded files.`);
    }
    
    /**
     * Installs trigger to capture onFormSubmit event when a form is submitted.
     * Ensures that the trigger is only installed once.
     * Called by setup().
     */
    function installTrigger_() {
      // Ensures existing trigger doesn't already exist.
      let propTriggerId = PropertiesService.getScriptProperties().getProperty('triggerUniqueId')
      if (propTriggerId !== null) {
        const triggers = ScriptApp.getProjectTriggers();
        for (let t in triggers) {
          if (triggers[t].getUniqueId() === propTriggerId) {
            console.log(`Trigger with the following unique ID already exists: ${propTriggerId}`);
            return;
          }
        }
      }
      // Creates the trigger if one doesn't exist.
      let triggerUniqueId = ScriptApp.newTrigger('onFormSubmit')
        .forForm(FormApp.getActiveForm())
        .onFormSubmit()
        .create()
        .getUniqueId();
      PropertiesService.getScriptProperties().setProperty('triggerUniqueId', triggerUniqueId);
      console.log(`Trigger with the following unique ID was created: ${triggerUniqueId}`);
    }
    
    /**
     * Removes all script properties and triggers for the project.
     * Use primarily to test setup routines.
     */
    function removeTriggersAndScriptProperties() {
      PropertiesService.getScriptProperties().deleteAllProperties();
      // Removes all triggers associated with project.
      const triggers = ScriptApp.getProjectTriggers();
      for (let t in triggers) {
        ScriptApp.deleteTrigger(triggers[t]);
      }
    }
    
    /**
     * Removes all form responses to reset the form.
     */
    function deleteAllResponses() {
      FormApp.getActiveForm().deleteAllResponses();
    }
    

스크립트 실행

  1. Apps Script 편집기에서 Setup.gs 파일로 전환합니다.
  2. 함수 드롭다운에서 setUp를 선택합니다.
  3. 실행을 클릭합니다.
  4. 메시지가 표시되면 스크립트를 승인합니다. OAuth 동의 화면에 이 앱은 확인되지 않았습니다라는 경고가 표시되면 고급 > {프로젝트 이름}으로 이동(안전하지 않음)을 선택하여 계속 진행합니다.

  5. 양식으로 돌아가서 미리보기 미리보기 아이콘를 클릭합니다.

  6. 양식에서 하위 폴더를 선택하고 파일을 업로드합니다.

  7. 제출을 클릭합니다.

  8. Drive로 이동하여 Drive에 파일 업로드 (파일 응답) 폴더를 엽니다. 업로드한 파일은 양식에서 선택한 하위 폴더에 있습니다.

참여자

이 샘플은 Google에서 Google 개발자 전문가의 도움을 받아 유지관리합니다.

다음 단계