為何捐款
API 瀏覽器
Uploader

Quasar 提供您透過 QUploader 元件上傳檔案的方式。

提示

如果您只需要輸入檔案,您可能會想考慮改用 QFile 檔案選擇器元件。

載入 QUploader API 中...

用法

警告

QUploader 需要後端伺服器來接收檔案。以下範例實際上不會上傳。

提示

QUploader 符合拖放規範。

警告

當使用 vee-validate 時,您必須重新命名 vee-validate 的 “fieldBagName” 設定,q-uploader 才能運作。

設計

基本



強制暗黑模式



上傳多個檔案

預設情況下,多個檔案將個別上傳 (每個檔案一個執行緒)。如果您希望所有檔案在單一執行緒中上傳,請使用 batch 屬性 (以下範例中的第二個 QUploader)。

多個



限制上傳

基本限制



提示

在上面的範例中,我們使用 accept 屬性。其值必須是以逗號分隔的唯一檔案類型指定符號列表。對應到原生 input type=file 元素的 ‘accept’ 屬性。 更多資訊

警告

accept 屬性的建議格式為 <mediatype>/<extension>。範例:“image/jpeg”、“image/png”。QUploader 在底層使用 <input type="file">,並且完全依賴主機瀏覽器來觸發檔案選擇器。如果 accept 屬性 (套用至輸入) 不正確,螢幕上將不會出現檔案選擇器,或出現但它會接受所有檔案類型。

您也可以套用自訂篩選器 (在使用者選擇檔案後執行)

篩選器



新增標頭

使用 headers 來設定要與上傳請求一起傳送的額外 XHR 標頭。如果您需要嵌入其他欄位,也請查看 API 中的 form-fields 屬性。

標頭



提示

這兩個屬性 (headersform-fields) 也可以作為函數使用 ((files) => Array),讓您可以根據要上傳的檔案動態設定它們。

還有 with-credentials 屬性,它會將上傳過程使用的 XHR 上的 withCredentials 設定為 true

處理上傳

檔案選取時自動上傳



自訂上傳 URL



提示

您也可以透過 headersmethod 屬性自訂 HTTP 標頭和 HTTP 方法。請查看 QUploader API 章節。

Factory 函數

您可以使用 factory 屬性,它必須是一個函數。此函數可以傳回一個物件或一個解析為物件的 Promise (如果 Promise 失敗,則會發出 @factory-failed 事件)。

上述物件可以覆寫以下 QUploader 屬性:urlmethodheadersformFieldsfieldNamewithCredentialssendRaw。此物件的屬性也可以是函數 (形式為 (file[s]) => value)

基於 Promise 的 Factory 函數



您也可以使用 factory 函數屬性並立即傳回相同的物件。如果您想同時設定多個屬性 (如上所述),這很有用

立即傳回 Factory 函數



插槽

在下面的範例中,我們展示了預設標頭的等效項目。另請注意您可以使用的某些布林範圍屬性:scope.canAddFilesscope.canUploadscope.isUploading

警告

請注意,您必須安裝並使用另一個元件 (QUploaderAddTrigger) 才能將檔案新增至佇列。此元件需要放置在具有 position: relative 的 DOM 節點下 (提示:QBtn 已具有此屬性),並且會在使用者點擊其父節點時自動注入必要的事件 (請勿手動新增 @click="scope.pickFiles")。如果觸發器無法運作,請檢查您是否有在其上方呈現的元素,並相應地變更 QUploaderAddTrigger 的 zIndex。

自訂標頭



自訂檔案列表



伺服器端點範例

QUploader 預設使用 HTTP(S) 協定上傳檔案 (但它不限於此,您將在本節之後看到)。

提示

絕非必須像下面這樣使用 Nodejs 伺服器或 Spring 或 ASP.NET – 您可以隨心所欲地處理檔案上傳,只要您使用的方法符合 HTTP 協定即可。PHP 範例。更多資訊

Nodejs

以下是以 Nodejs 撰寫的基本伺服器範例。它除了接收檔案外,什麼都不做,因此請將其視為起點。

const
  express = require('express'),
  app = express(),
  formidable = require('formidable'),
  path = require('node:path'),
  fs = require('node:fs'),
  throttle = require('express-throttle-bandwidth')

const
  port = process.env.PORT || 4444,
  folder = path.join(__dirname, 'files')

if (!fs.existsSync(folder)) {
  fs.mkdirSync(folder)
}

app.set('port', port)
app.use(throttle(1024 * 128)) // throttling bandwidth

app.use((req, res, next) => {
  res.header('Access-Control-Allow-Origin', '*')
  res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept')
  next()
})

app.post('/upload', (req, res) => {
  const form = new formidable.IncomingForm()

  form.uploadDir = folder
  form.parse(req, (_, fields, files) => {
    console.log('\n-----------')
    console.log('Fields', fields)
    console.log('Received:', Object.keys(files))
    console.log()
    res.send('Thank you')
  })
})

app.listen(port, () => {
  console.log('\nUpload server running on https://127.0.0.1:' + port)
})

ASP.NET MVC/Core

QUploader 與 Microsoft ASP.NET MVC/Core 2.x Web API 後端無縫整合。在您的 Vue 檔案中,使用所需的 Web API 端點設定 QUploader 元件

<q-uploader
  url="https://127.0.0.1:4444/fileuploader/upload"
  label="Upload"
  style="max-width: 300px"
/>

如果您的伺服器需要身分驗證 (例如 JWT 權杖),請使用 QUploader 的 factory 函數來指定 QUploader 將使用的 xhr 標頭。例如

<template>
  <q-uploader
    label="Upload"
    :factory="factoryFn"
    style="max-width: 300px"
  />
</template>

<script>
export default {
  methods: {
    factoryFn (file) {
      return new Promise((resolve, reject) => {
        // Retrieve JWT token from your store.
        const token = "myToken";
        resolve({
          url: 'https://127.0.0.1:4444/fileuploader/upload',
          method: 'POST',
          headers: [
            { name: 'Authorization', value: `Bearer ${token}` }
          ]
        })
      })
    }
  }
}
</script>

QUploader 的檔案酬載將是一個正確格式的 IFormFileCollection 物件,您可以透過 ASP.NET Web API 控制器的 .Request 屬性讀取。ASP.NET Core 2.2 控制器

[Route("api/[controller]")]
[ApiController]
public class FileUploaderController : ControllerBase
{
    [HttpPost]
    public async Task upload()
    {
        // Request's .Form.Files property will
        // contain QUploader's files.
        var files = this.Request.Form.Files;
        foreach (var file in files)
        {
            if (file == null || file.Length == 0)
                continue;

            // Do something with the file.
            var fileName = file.FileName;
            var fileSize = file.Length;
            // save to server...
            // ...
        }
    }
}

Spring

以下是 Spring 範例。屬性 fieldName="file"@RequestPart(value = "file") 對應。

// java
@RestController
public class UploadRest {
	@PostMapping("/upload")
	public void handleFileUpload(@RequestPart(value = "file") final MultipartFile uploadfile) throws IOException {
		saveUploadedFiles(uploadfile);
	}

	private String saveUploadedFiles(final MultipartFile file) throws IOException {
		final byte[] bytes = file.getBytes();
		final Path path = Paths.get("YOUR_ABSOLUTE_PATH" + file.getOriginalFilename());
		Files.write(path, bytes);
	}
}

// html
<q-uploader field-name="file" url="YOUR_URL_BACK/upload" with-credentials />

Python/Flask

// python
from flask import Flask, request
from werkzeug import secure_filename
from flask_cors import CORS
import os

app = Flask(__name__)

# This is necessary because QUploader uses an AJAX request
# to send the file
cors = CORS()
cors.init_app(app, resource={r"/api/*": {"origins": "*"}})

@app.route('/upload', methods=['POST'])
def upload():
    for fname in request.files:
        f = request.files.get(fname)
        print(f)
        f.save('./uploads/%s' % secure_filename(fname))

    return 'Okay!'

if __name__ == '__main__':
    if not os.path.exists('./uploads'):
        os.mkdir('./uploads')
    app.run(debug=True)

Julia/Genie

# Julia Genie

using Genie, Genie.Requests, Genie.Renderer

Genie.config.cors_headers["Access-Control-Allow-Origin"]  =  "*"
Genie.config.cors_headers["Access-Control-Allow-Headers"] = "Content-Type"
Genie.config.cors_headers["Access-Control-Allow-Methods"] = "GET,POST,PUT,DELETE,OPTIONS"
Genie.config.cors_allowed_origins = ["*"]

#== server ==#

route("/") do
  "File Upload"
end

route("/upload", method = POST) do
  if infilespayload(:img)                 # :img is file-name
    @info filename(filespayload(:img))    # file-name="img"
    @info filespayload(:img).data

    open("upload/file.jpg", "w") do io
      write(io, filespayload(:img).data)
    end
  else
    @info "No image uploaded"
  end

  Genie.Renderer.redirect(:get)
end

isrunning(:webserver) || up()

Perl/Mojolicious

# Perl

use Mojolicious::Lite -signatures;

# CORS
app->hook(after_dispatch => sub {
    my $c = shift;
    $c->res->headers->header('Access-Control-Allow-Origin' => '*');
});
options '*' => sub ($c) {
   $c->res->headers->header('Access-Control-Allow-Methods' => 'GET, OPTIONS, POST, DELETE, PUT');
   $c->res->headers->header('Access-Control-Allow-Headers' => 'Content-Type');
   $c->render(text => '');
};

post '/upload' => sub ($c) {
   my $uploads = $c->req->uploads('files');

   foreach my $f (@{$uploads}) {
      $f->move_to('/tmp/' . $f->filename);
   }

   $c->render(text => 'Saved!');
};

app->start;

支援其他服務

QUploader 目前支援透過 HTTP(S) 協定上傳。但您也可以擴展元件以支援其他服務。例如 Firebase。以下是如何做到。

感謝協助

我們非常樂意接受關於支援其他上傳服務的 PR,以便其他人也能受益。點擊此頁面底部的 Edit this page in browser 連結或頁面頂部的鉛筆圖示。

以下範例說明您需要提供給 createUploaderComponent() Quasar 工具的 API。這將建立一個 Vue 元件,您可以將其匯入到您的應用程式中。

MyUploader.js

import { createUploaderComponent } from 'quasar'
import { computed } from 'vue'

// export a Vue component
export default createUploaderComponent({
  // defining the QUploader plugin here

  name: 'MyUploader', // your component's name

  props: {
    // ...your custom props
  },

  emits: [
    // ...your custom events name list
  ],

  injectPlugin ({ props, emit, helpers }) {
    // can call any other composables here
    // as this function will run in the component's setup()

    // [ REQUIRED! ]
    // We're working on uploading files
    const isUploading = computed(() => {
      // return <Boolean>
    })

    // [ optional ]
    // Shows overlay on top of the
    // uploader signaling it's waiting
    // on something (blocks all controls)
    const isBusy = computed(() => {
      // return <Boolean>
    })

    // [ REQUIRED! ]
    // Abort and clean up any process
    // that is in progress
    function abort () {
      // ...
    }

    // [ REQUIRED! ]
    // Start the uploading process
    function upload () {
      // ...
    }

    return {
      isUploading,
      isBusy,

      abort,
      upload
    }
  }
})

提示

  • 對於以此外掛程式形式的預設 XHR 實作,請查看 原始碼
  • 對於 UMD 版本,請使用 Quasar.createUploaderComponent({ ... })

然後,您可以在 Vue 中全域註冊此元件,或者匯入它並將其新增至 Vue 元件中的 “components: {}”。

// globally registering your component in a boot file
import MyUploader from '../../path/to/MyUploader' // the file from above

export default ({ app }) {
  app.component('MyUploader', MyUploader)
}

// or declaring it in a .vue file
import MyUploader from '../../path/to/MyUploader' // the file from above
export default {
  // ...
  components: {
    // ...
    MyUploader
  }
}

如果您使用 TypeScript,您需要註冊新的元件類型,以允許 Volar 為您自動完成屬性和插槽。

import {
  GlobalComponentConstructor,
  QUploaderProps,
  QUploaderSlots,
} from 'quasar';

interface MyUploaderProps extends QUploaderProps {
  // .. add custom props
  freeze: boolean;
  // .. add custom events
  onFreeze: boolean;
}

declare module 'vue' {
  interface GlobalComponents {
    MyUploader: GlobalComponentConstructor<MyUploaderProps, QUploaderSlots>;
  }
}