簡體   English   中英

VueJS:$_FILES 不接收從前端到后端的數據

[英]VueJS: $_FILES Not Receiving Data from Frontend to Backend

我嘗試了不同的方法將圖像上傳到 SQL,但問題是我無法在后端獲取文件的數據。 一些答案說這是因為表單沒有 enctype,但我也嘗試過。 我不確定它是否適用於 Vue,因為我使用的是 axios。 此外,我嘗試使用 uploadFile 作為 axios 的參數,因此 $_FILES 也將其讀取為 $_GET,因為它也適用於我的一些代碼。 順便說一句,submitTestData 位於另一個文件夾中的另一個文件中,該文件夾位於商店 (VueX) 內。 我使用 dispatch 將數據發送到 store,以便最終將 post 方法發送到后端。

store.js

  submitTestData2 ({ commit }, payload) {
        console.log(payload.uploadFile)
        return new Promise((resolve, reject) => {
          const formData = new FormData()
          formData.append('uploadFile', payload.uploadFile)
          const config = {
            headers: { 'Content-Type': 'multipart/form-data' }
          }
          axios
            .post(
              'http://localhost/MyComposer/',
              {
                token: payload.token,
                subject: payload.subject,
                timer: payload.timer,
                question: payload.question,
                answer: payload.answer,
                formData
              },
              {
                params: {
                  submitId: 7,
                  uploadFile: formData
                },
                config
              }
            )
            .then(response => {
              commit('SAVE_TEST_DATA', response.data)
              console.log(response)
              resolve(response)
            })
            .catch(error => {
              reject(error)
            })
        })
      },

添加測試.vue

 <q-form class="q-pa-md" align="center">
        <h5>Test Creation Form</h5>
        <!-- <q-btn label="Add Subject" color="primary" to="/addsub" /> -->
        <q-btn label="Return to Main" to="/dashboard" color="primary" />&nbsp;
        <q-btn label="View Student Answers" color="primary" to="/subjectntestlist" />&nbsp;
        <q-btn label="View Student Profile" color="primary" to="/studentprofile" />
        <q-card>
          <q-separator />
          <q-card-section class="q-gutter-md" align="center">
            <q-select
              filled
              v-model="testItems.subject"
              :options="option"
              map-options
              emit-value
              option-value="subjectId"
              option-label="subjectName"
              label="Choose a Subject"
              style="width: 250px"
              stack-label
              input-debounce="0"
            />
            <q-file
              filled
              v-model="testItems.uploadFile"
              label="Upload File Here"
              style="width: 500px"
            />
            <h5>Timer</h5>
            <q-input label="Minute(s)" name="timer" v-model="testItems.timer" style="width: 500px" />
            <h5>Question</h5>
            <q-input name="question" v-model="testItems.question" style="width: 500px" />
            <h5>Answer</h5>
            <q-input name="answer" v-model="testItems.answer" style="width: 500px" />
            <br />
            <q-btn label="Save Test Item" @click="submitTestData" />
          </q-card-section>
        </q-card>
      </q-form>

submitTestData1() {
      this.$store
        .dispatch("submitTestData2", {
          token: this.token,
          subject: this.testItems.subject,
          question: this.testItems.question,
          answer: this.testItems.answer,
          uploadFile: this.testItems.uploadFile,
          timer: this.testItems.timer
        })
        .then(response => {
          alert("Test was added to the database!");
        });
    },
<?php

namespace Classes;

use Classes\ConnectDb;

class TestClass
{
    public function addTest()
    {
        $datab = new ConnectDb;
        $db = $datab->Connect();


        if (isset($_GET['submitId']) && $_GET['submitId'] == 7) {

            $testdata = file_get_contents('php://input');
            $testdecodedData = json_decode($testdata);
            $subject = $testdecodedData->{'subject'};
            $access_id = $testdecodedData->{'token'};
            $question = $testdecodedData->{'question'};
            $answer = $testdecodedData->{'answer'};
            // $testImage = $testdecodedData->{'uploadFile'};
            $testTimer = $testdecodedData->{'timer'};

            $name = $_FILES['uploadFile'];

            echo $name;

            $testdataDb = array(
                'SubjectId' => $subject,
                'AccessId' => $access_id,
                'Question' => $question,
                'Answer' => $answer,
                // 'TestImage' => $testImage,
                'Timer' => $testTimer * 60
            );
            $testId = $db->insert('testdetails', $testdataDb);
            if ($testId) {
                echo 'Test details were added!';
            }
        }
    }

您需要像下面一樣通過 header

submitTestData ({ commit }, payload) {
    console.log(payload.uploadFile)
    return new Promise((resolve, reject) => {
      const formData = new FormData()
      formData.append('uploadFile', payload.uploadFile)
      const config = {
            headers:{'Content-Type' : 'multipart/form-data'}
       };
      axios
        .post('http://localhost/MyComposer/',formData,config)
        .then(response => {
          commit('SAVE_TEST_DATA', response.data)
          console.log(response)
          resolve(response)
        })
        .catch(error => {
          reject(error)
        })
    })
  },

看起來您沒有從 $_FILES 超全局中正確獲取文件名。 您的代碼中有 $_FILES['uploadFile'] 但是 $_FILES 數組的結構類似於上傳( uploadFile 代表表單中文件上傳輸入字段的名稱,因此這因輸入字段名稱而異):

Array
(
    [uploadFile] => Array
            (
                      [name] => users_file_name.png
                      [type] => image/png
                      [tmp_name] => /path/to/temporary/files/abc123
                      [error] => 0
                      [size] => 12345
            )
)

因此,要訪問文件名,您需要將代碼更改為:$_FILES['uploadFile']['name']。

實際文件存儲在服務器上的臨時文件位置,因此您需要獲取該臨時文件並將其移動到服務器上的其他位置。 大多數人都會這樣做:

$temp_file = $_FILES['uploadFile']['tmp_name'];
$target_upload_destination = 'path/to/desired/directory/' . basename($_FILES['uploadFile']['name']);

// Check to see that the file was moved to desired destination successfully
if (move_uploaded_file($temp_file, $target_upload_destination)) {
      // do something here
    } else {
      // Fallback logic here
}

顯然,在您的服務器上移動臨時文件之前應該進行一些邏輯檢查,但是,我希望您了解這背后的基本概念。 為數據庫插入移動后,您應該使用文件路徑。 我希望這有幫助。

在您的客戶端和服務器端代碼中都有幾個問題。

客戶端

如果要發送文件,則必須使用帶有FormData有效負載的multipart/form-data請求。 您似乎正在嘗試將 JSON 有效負載與嵌入式FormData結合起來,這根本不起作用。

你需要這樣的東西

const formData = new FormData()
Object.entries(payload).forEach(([key, val]) => {
  // adds all the properties in "payload" to "formData"
  formData.append(key, val)
})

axios.post('http://localhost/MyComposer', formData, {
  params: { submitId: 7 }
})

❗ 請注意,沒有添加Content-type header。 傳遞FormData實例會自動將其設置為所需的 mime 邊界。

服務器端

在 PHP 端,您可以從$_POST獲取tokensubjecttimer等值

$subject = $_POST['subject'];
$access_id = $_POST['token'];
$question = $_POST['question'];
// etc

上傳文件將在$_FILES中提供(參見https://www.php.net/manual/features.file-upload.post-method.php

$uploadFile = $_FILES['uploadFile'];
if (!$uploadFile['error']) {
  echo $uploadFile['name'];
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM