API 浏览器
上传器

Quasar 提供了一种通过 QUploader 组件上传文件的方法。

¥Quasar supplies a way for you to upload files through the QUploader component.

提示

如果你只需要一个输入文件,你可能需要考虑使用 QFile 选择器组件。

¥If all you want is an input file, you might want to consider using QFile picker component instead.

Loading QUploader API...

用法(Usage)

¥Usage

警告

QUploader 需要后端服务器来接收文件。以下示例实际上不会上传。

¥QUploader requires a back-end server to receive the files. The examples below will not actually upload.

提示

QUploader 符合 drag and drop 标准。

¥QUploader is drag and drop compliant.

警告

使用 vee-validate 时,你必须重命名 vee-validate 的 “fieldBagName” 配置才能使 q-uploader 正常工作。

¥When using vee-validate, you have to rename the “fieldBagName” configuration of vee-validate for the q-uploader to work.

设计(Design)

¥Design

Basic



Force dark mode



上传多个文件(Uploading multiple files)

¥Uploading multiple files

默认情况下,多个文件将单独上传(每个文件一个线程)。如果你希望所有文件都在单个线程中上传,请使用 batch 属性(下面示例中的第二个 QUploader)。

¥By default, multiple files will be uploaded individually (one thread per file). Should you want all files to be uploaded in a single thread, use the batch property (second QUploader in the example below).

Multiple



限制上传(Restricting upload)

¥Restricting upload

Basic restrictions



提示

在上面的例子中,我们使用了 accept 属性。它的值必须是以逗号分隔的唯一文件类型说明符列表。映射到原生输入 type=file 元素的 ‘accept’ 属性。更多信息

¥In the example above, we’re using accept property. Its value must be a comma separated list of unique file type specifiers. Maps to ‘accept’ attribute of native input type=file element. More info.

警告

accept 属性的推荐格式为 <mediatype>/<extension>。示例:“image/jpeg”, “image/png”.QUploader 底层使用 <input type="file">,完全依赖主机浏览器来触发文件选择器。如果 accept 属性(应用于输入)不正确,则屏幕上不会显示文件选择器,或者虽然显示文件选择器,但它会接受所有文件类型。

¥Recommended format for the accept property is <mediatype>/<extension>. Examples: “image/jpeg”, “image/png”. QUploader uses an <input type="file"> under the hood and it relies entirely on the host browser to trigger the file picker. If the accept property (that gets applied to the input) is not correct, no file picker will appear on screen or it will appear but it will accept all file types.

你还可以应用自定义过滤器(在用户选择文件后执行):

¥You can also apply custom filters (which are executed after user picks files):

Filter



添加标题(Adding headers)

¥Adding headers

使用 headers 设置要随上传请求一起发送的附加 XHR 标头。如果你需要嵌入其他字段,还请查看 API 中的 form-fields 属性。

¥Use headers for setting additional XHR headers to be sent along the upload request. Also check form-fields prop in the API, if you need additional fields to be embedded.

Headers



提示

这两个 props(headersform-fields)也可以用作函数((files) => Array),允许你根据要上传的文件动态设置它们。

¥These two props (headers and form-fields) can be used as a function too ((files) => Array), allowing you to dynamically set them based on the files that are to be uploaded.

还有一个 with-credentials 属性,用于在上传过程使用的 XHR 上将 withCredentials 设置为 true

¥There is also the with-credentials property, which sets withCredentials to true on the XHR used by the upload process.

处理上传(Handling upload)

¥Handling upload

Auto upload on file selection



Custom upload URL



提示

你还可以通过 headersmethod 属性自定义 HTTP 标头和 HTTP 方法。检查 QUploader API 部分。

¥You can also customize the HTTP headers and HTTP method through headers and method props. Check QUploader API section.

工厂函数(Factory function)

¥Factory function

你可以使用 factory 属性,该属性必须是一个函数。此函数可以返回一个对象或一个解析为对象的 Promise(如果 Promise 失败,则会发出 @factory-failed 事件)。

¥There is a factory prop you can use which must be a Function. This function can return either an Object or a Promise resolving with an Object (and in case the Promise fails, @factory-failed event is emitted).

上面描述的对象可以覆盖以下 QUploader 属性:url, method, headers, formFields, fieldName, withCredentials, sendRaw).此对象的 props 也可以是函数(形式为 (file[s]) => value):

¥The Object described above can override the following QUploader props: url, method, headers, formFields, fieldName, withCredentials, sendRaw). The props of this Object can be Functions as well (of form (file[s]) => value):

Promise-based factory function



你还可以使用 factory 函数属性并立即返回相同的对象。如果你想同时设置多个 props(如上所述),这将非常有用:

¥You can also use the factory Function prop and return immediately the same Object. This is useful if you want to set multiple props (described above) simultaneously:

Immediate return factory function



插槽(Slots)

¥Slots

在下面的示例中,我们展示了与默认标题等效的效果。另请注意一些你可以使用的布尔作用域属性:scope.canAddFiles, scope.canUpload, scope.isUploading.

¥In the example below we’re showing the equivalent of the default header. Also notice some Boolean scope properties that you can use: scope.canAddFiles, scope.canUpload, scope.isUploading.

警告

请注意,你必须安装并使用另一个组件 (QUploaderAddTrigger) 才能将文件添加到队列。此组件需要放置在具有 position: relative 的 DOM 节点下(提示:QBtn 已经具有 position: relative),并且会在用户点击其父节点时自动注入必要的事件(请勿手动添加 @click="scope.pickFiles")。如果触发器不起作用,请检查其上方是否渲染了元素,并相应地更改 QUploaderAddTrigger 的 zIndex。

¥Notice that you must install and use one more component (QUploaderAddTrigger) in order to be able to add files to the queue. This component needs to be placed under a DOM node which has position: relative (hint: QBtn has it already) and will automatically inject the necessary events when user clicks on its parent (do NOT manually add @click="scope.pickFiles"). If the trigger is not working, check if you have an element rendered above it and change the zIndex of QUploaderAddTrigger accordingly.

Custom header



Custom files list



服务器端点示例(Server endpoint examples)

¥Server endpoint examples

QUploader 默认使用 HTTP(S) 协议上传文件(但并不局限于此,你将在下一节中看到)。

¥QUploader works by default with the HTTP(S) protocol to upload files (but it’s not limited to it as you’ll see in the section following this one).

提示

它并非必须使用 Nodejs 服务器、Spring 或 ASP.NET(如下所示) - 你可以根据需要处理文件上传,只要你使用的方法符合 HTTP 协议即可。使用 PHP 的示例。

¥It is by no means required to use a Nodejs server or Spring or ASP.NET like below – you can handle file upload however you want, as long as the method you are using fits the HTTP protocol. Example with PHP.

Nodejs(Nodejs)

以下是一个用 Nodejs 编写的基本服务器示例。它除了接收文件外什么也不做,所以可以将其作为一个起点。

¥Below is a basic server example written in Nodejs. It does nothing other than receiving the files, so consider it as a starting point.

import fs from 'node:fs'
import path from 'node:path'
import express from 'express'
import formidable from 'formidable'
import throttle from 'express-throttle-bandwidth'

const app = express()

const port = process.env.PORT || 4444
const folder = fileURLToPath(new URL('./files', import.meta.url))

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(ASP.NET MVC/Core)

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

¥QUploader seamlessly integrates with a Microsoft ASP.NET MVC/Core 2.x Web API backend. In your Vue file, configure the QUploader component with the desired Web API endpoint:

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

如果你的服务器需要身份验证(例如 JWT 令牌),请使用 QUploader 的工厂函数指定 QUploader 将使用的 xhr 标头。例如:

¥If your server requires authentication such as a JWT token, use QUploader’s factory function to specify the xhr header that will be used by QUploader. For example:

<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 的文件负载将是一个格式正确的 IFormFileCollection 对象,你可以通过 ASP.NET Web API 控制器的 .Request 属性读取该对象。ASP.NET Core 2.2 控制器:

¥The file(s) payload of QUploader will be a properly formed IFormFileCollection object that you can read via your ASP.NET Web API controller’s .Request property. ASP.NET Core 2.2 Controller:

[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") 映射。

¥Below is a Spring example. Attribute fieldName="file" is mapping with @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/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)

# 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/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;

支持其他服务(Supporting other services)

¥Supporting other services

QUploader 目前支持通过 HTTP(S) 协议上传。但是你也可以扩展组件以支持其他服务。例如 Firebase。以下是操作方法。

¥QUploader currently supports uploading through the HTTP(S) protocol. But you can extend the component to support other services as well. Like Firebase for example. Here’s how you can do it.

感谢帮助

我们非常乐意接受支持其他上传服务的 PR,以便其他人也能从中受益。点击此页面底部的 Edit this page in browser 链接或页面顶部的铅笔图标。

¥We’d be more than happy to accept PRs on supporting other upload services as well, so others can benefit. Hit the Edit this page in browser link at bottom of this page or the pencil icon at the top of the page.

以下是使用你需要提供给 createUploaderComponent() Quasar 实用程序的 API 的示例。这将创建一个 Vue 组件,你可以在应用中导入它。

¥Below is an example with the API that you need to supply to the createUploaderComponent() Quasar util. This will create a Vue component that you can import in your app.

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

TIPS

  • 有关此类插件形式的默认 XHR 实现,请查看 源代码

    ¥For the default XHR implementation in the form of such a plugin, check out source code.

  • 对于 UMD 版本,请使用 Quasar.createUploaderComponent({ ... })

    ¥For the UMD version use Quasar.createUploaderComponent({ ... }).

然后,你需要在 Vue 中全局注册此组件,或者导入它并将其添加到“components:”中。{}" 在你的 Vue 组件中。

¥Then you register this component globally with Vue or you import it and add it to the “components: {}” in your 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。

¥If you’re using TypeScript, you’d need to register the new component types to allow Volar to autocomplete props and slots for you.

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