Quasar为您提供了一种通过QUploader组件上传文件的方法。
TIP
如果您只需要一个输入文件,您可能需要考虑使用QFile picker组件。
QUploader API
用法
WARNING
QUploader需要后端服务器来接收文件。 以下示例实际上不会上传。
TIP
QUploader兼容“拖放”。
WARNING
使用vee-validate时,必须重新命名vee-validate的“fieldBagName”配置,q-uploader才能正常工作。
设计
上传多个文件
默认情况下,将分别上传多个文件(每个文件一个线程)。 如果您希望所有文件都在一个线程中上传,请使用batch
属性(在下面的示例中为第二个QUploader)。
限制上传
TIP
在上面的示例中,我们使用了accept
属性。 其值必须是用逗号分隔的唯一文件类型说明符列表。 对应到原生input type = file元素的’accept’属性。 更多信息。
WARNING
accept
属性的推荐格式为<mediatype>/<extension>
。 示例:“image/jpeg”,“image/png”。 QUploader在底层使用了<input type="file">
,它完全依靠宿主浏览器来触发文件选择器。 如果accept
属性(应用于input的属性)不正确,则屏幕上不会出现文件选择器,或者会出现但是它将接受所有文件类型。
您还可以应用自定义过滤器(在用户选择文件后执行):
添加头部
使用headers
设置附加的XHR头部,以随上传请求一起发送。 如果需要嵌入其他字段,还请检查API中的form-fields
属性。
TIP
这两个属性(headers
和form-fields
)也可以用作函数((files) => Array
),允许您根据要上传的文件动态设置它们。
还有一个with-credentials
属性,它将上传过程使用的XHR的withCredentials
设置为“true”。
处理上传
TIP
您也可以通过headers
和method
属性自定义HTTP头部和HTTP方法。 检查QUploader API部分。
工厂函数
您可以使用一个factory
属性,该属性必须是一个函数。 该函数可以返回一个对象或一个用对象解决的Promise(并且如果Promise失败,则会发出@factory-failed
事件)。
上述对象可以覆盖以下QUploader属性:url
、method
、headers
、formFields
、fieldName
、withCredentials
、sendRaw
。 这个对象的属性也可以是函数(形式为(file[s]) => value
):
您还可以使用factory
函数属性并立即返回相同的对象。 如果要同时设置多个属性(如上所述),这将很有用:
插槽
在下面的示例中,我们显示了等效于默认头部的内容。 还要注意一些可以使用的布尔scope属性:scope.canAddFiles
、scope.canUpload
、scope.isUploading
。
WARNING
请注意,您必须安装并使用另一个组件(QUploaderAddTrigger)才能将文件添加到队列中。 该组件需要放置在具有position: relative
(提示:QBtn已经拥有)的DOM节点下,并且在用户单击其父元素时将自动注入必要的事件(请勿手动添加@click="scope.pickFiles"
)。如果触发器不工作,请检查是否在其上方渲染了元素,并相应地更改QUploaderAddTrigger的zIndex。
服务器端例子
默认情况下,Quploader与HTTP(S)协议一起使用来上传文件(但不限于此,正如您将在此后面的部分中看到的那样)。
TIP
完全不需要像下面那样使用Nodejs服务器或Spring或ASP.NET-只要您使用的方法适合HTTP协议,就可以根据需要处理文件上传。 PHP的示例。
Nodejs
以下是用Node.js编写的基本服务器示例。 除了接收文件外,它什么也不做,因此请以它为起点。
const
express = require('express'),
app = express(),
formidable = require('formidable'),
path = require('path'),
fs = require('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)) // 节流带宽
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文件中,为QUploader组件配置所需的Web API端点:
<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) => {
// 从您的存储中检索JWT令牌。
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控制器:
[Route("api/[controller]")]
[ApiController]
public class FileUploaderController : ControllerBase
{
[HttpPost]
public async Task upload()
{
// 请求的.Form.Files属性
// 将包含QUploader的文件。
var files = this.Request.Form.Files;
foreach (var file in files)
{
if (file == null || file.Length == 0)
continue;
// 对文件进行处理。
var fileName = file.FileName;
var fileSize = file.Length;
// 保存到服务器...
// ...
}
}
}
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()
支持其他服务
QUploader当前支持通过HTTP(S)协议上载。 但是您也可以扩展该组件以支持其他服务。 例如Firebase。 告诉你如何做到。
乐意接受帮助
我们也很乐意接受支持其他上传服务的PR,因此其他人可以从中受益。点击本页底部的 "在浏览器中编辑此页面"链接或页面顶部的铅笔图标。
下面是一个例子,你需要向createUploaderComponent()
Quasar util提供API。这将创建一个Vue组件,你可以在你的应用程序中导入。
// MyUploader.js
import { createUploaderComponent } from 'quasar'
import { computed } from 'vue'
// 输出一个Vue组件
export default createUploaderComponent({
// 在此定义QUploader插件
name: 'MyUploader', // 您的组件的名称
props: {
// ...您的定制属性
},
emits: [
// ...您的自定义事件名称列表
],
injectPlugin ({ props, emit, helpers }) {
// 可以在这里调用任何其他的组件
// 因为这个函数将在组件的setup()中运行。
// [必需]
// 我们正在上传文件
const isUploading = computed(() => {
// 返回<Boolean>
})
// [可选]
// 显示上传器顶部的覆盖层,
// 表明它正在等待某件事
// (阻止所有控件)
const isBusy = computed(() => {
// 返回<Boolean>
})
// [必需]
// 中止并清理
// 正在进行的任何进程
function abort () {
// ...
}
// [ 必需!]
// 开始上传过程
function upload () {
// ...
}
return {
isUploading,
isBusy,
abort,
upload
}
}
})
TIPS
- 对于这种插件形式的默认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/runtime-core' {
interface GlobalComponents {
MyUploader: GlobalComponentConstructor<MyUploaderProps, QUploaderSlots>;
}
}