为什么捐赠
API 资源管理器
上传器

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 属性,您可以使用它,它必须是一个函数。此函数可以返回一个对象或一个解析为对象的 Promise(如果 Promise 失败,则会发出 @factory-failed 事件)。

上面描述的对象可以覆盖以下 QUploader 属性:urlmethodheadersformFieldsfieldNamewithCredentialssendRaw)。此对象中的属性也可以是函数(形式为 (file[s]) => value)。

基于 Promise 的工厂函数



您也可以使用 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 http://localhost:' + port)
})

ASP.NET MVC/Core

QUploader 可以与 Microsoft ASP.NET MVC/Core 2.x Web API 后端无缝集成。在您的 Vue 文件中,使用所需的 Web API 端点配置 QUploader 组件

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

如果您的服务器需要身份验证,例如 JWT 令牌,请使用 QUploader 的工厂函数指定 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: 'http://localhost:4444/fileuploader/upload',
          method: 'POST',
          headers: [
            { name: 'Authorization', value: `Bearer ${token}` }
          ]
        })
      })
    }
  }
}
</script>

QUploader 的文件(s) 负载将是一个正确格式的 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 组件中的“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 可以为您自动完成 props 和 slots。

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>;
  }
}