Google 云端硬盘(Web)中的下载是如何工作的?
How does download in Google Drive (Web) work?
我目前正在 Web 应用程序中实现文件下载。
我在弹出窗口拦截器上遇到了一些困难,下载需要在用户交互后立即开始,所以不可能有服务器往返。
现在我注意到,例如 Goolge Drive 允许您下载文件夹。当您这样做时,他们的服务器首先创建一个压缩的 zip 文件,这需要一些时间 time.When 服务器完成后,下载会立即开始,无需其他用户交互。
现在我想知道如何做到这一点?
我写了一个函数来通过 url 下载文件。
在你的情况下,你必须使用 ajax 请求在服务器上制作一个 zip 文件,然后返回 url 和 运行 下面的函数来下载:
function download(url, filename){
fetch(url)
.then(resp => resp.blob())
.then(blob => {
const url = window.URL.createObjectURL(blob);
const a = document.createElement('a');
a.style.display = 'none';
a.href = url;
a.download = filename;
document.body.appendChild(a);
a.click();
window.URL.revokeObjectURL(url);
console.log('your file has downloaded!');
})
.catch(() => console.log('Download failed!'));
}
在此处测试代码笔:download file via url
I noticed, that Google Drive for example allows you to download
folders. When you do that, their server first creates a compressed zip
file, which takes some time.
或者,您可以将目录的内容请求为 json,然后遍历 json 并将每个文件下载为 blob 并创建一个 zip 文件,唯一的阻塞是json 的请求,然后您可以显示每个下载文件的状态等。
可以这样做:
片段示例,使用 vue、s3 等
async download(bucket) {
this.$snackbar.show({
type: 'bg-success text-white',
message: 'Building Zip, please wait...'
})
//..eek fetch all items in bucket, plop into a zip, then trigger download
// - there is some limits on final filesize, will work around it by disabling download :)
// resolve objects
const objects = async(bucket) => new Promise(async(resolve, reject) => {
let objectStream = await this.state.host.client.listObjectsV2(bucket, '', true)
let objects = []
//
objectStream.on('data', (obj) => {
if (obj && (obj.name || obj.prefix)) {
this.$snackbar.show({
type: 'bg-success text-white',
message: 'Fetching: ' + obj.name
})
objects.push(obj)
}
})
objectStream.on('end', () => resolve(objects))
objectStream.on('error', (e) => reject(e))
})
// get an objects data
const getObject = (bucket, name) => new Promise((resolve, reject) => {
this.state.host.client.getObject(bucket, name, (err, dataStream) => {
let chunks = []
dataStream.on('data', chunk => {
this.$snackbar.show({
type: 'bg-success text-white',
message: 'Downloading: ' + name
})
chunks.push(chunk)
})
dataStream.on('end', () => resolve(Buffer.concat(chunks || [])))
})
})
// fetch objects info a zip file
const makeZip = (bucket, objects) => new Promise(async(resolve, reject) => {
let zip = new JSZip()
for (let i in objects) {
this.$snackbar.show({
type: 'bg-success text-white',
message: 'Zipping: ' + objects[i].name
})
zip.file(objects[i].name, await getObject(bucket, objects[i].name));
}
zip.generateAsync({
type: "blob"
}).then(content => {
this.$snackbar.show({
type: 'bg-success text-white',
message: 'Zip Created'
})
resolve(content)
})
})
// using FileSaver, download file
const downloadZip = (content) => {
this.$snackbar.show({
type: 'bg-success text-white',
message: `Downloading: ${bucket.name}.zip`
})
FileSaver.saveAs(content, `${bucket.name}.zip`)
}
try {
downloadZip(await makeZip(bucket.name, await objects(bucket.name)))
} catch (e) {
this.$snackbar.show({
type: 'bg-danger text-white',
message: e.message
})
console.error(e)
}
},
如果你想要一个丑陋的方式来下载目录,获取 json 列表然后将一堆 document.createElement('a')
放在 dom 和 a.setAttribute("target", "_blank")
上,但是你将打开一堆“另存为”对话框。
我目前正在 Web 应用程序中实现文件下载。 我在弹出窗口拦截器上遇到了一些困难,下载需要在用户交互后立即开始,所以不可能有服务器往返。 现在我注意到,例如 Goolge Drive 允许您下载文件夹。当您这样做时,他们的服务器首先创建一个压缩的 zip 文件,这需要一些时间 time.When 服务器完成后,下载会立即开始,无需其他用户交互。
现在我想知道如何做到这一点?
我写了一个函数来通过 url 下载文件。 在你的情况下,你必须使用 ajax 请求在服务器上制作一个 zip 文件,然后返回 url 和 运行 下面的函数来下载:
function download(url, filename){
fetch(url)
.then(resp => resp.blob())
.then(blob => {
const url = window.URL.createObjectURL(blob);
const a = document.createElement('a');
a.style.display = 'none';
a.href = url;
a.download = filename;
document.body.appendChild(a);
a.click();
window.URL.revokeObjectURL(url);
console.log('your file has downloaded!');
})
.catch(() => console.log('Download failed!'));
}
在此处测试代码笔:download file via url
I noticed, that Google Drive for example allows you to download folders. When you do that, their server first creates a compressed zip file, which takes some time.
或者,您可以将目录的内容请求为 json,然后遍历 json 并将每个文件下载为 blob 并创建一个 zip 文件,唯一的阻塞是json 的请求,然后您可以显示每个下载文件的状态等。
可以这样做:
片段示例,使用 vue、s3 等
async download(bucket) {
this.$snackbar.show({
type: 'bg-success text-white',
message: 'Building Zip, please wait...'
})
//..eek fetch all items in bucket, plop into a zip, then trigger download
// - there is some limits on final filesize, will work around it by disabling download :)
// resolve objects
const objects = async(bucket) => new Promise(async(resolve, reject) => {
let objectStream = await this.state.host.client.listObjectsV2(bucket, '', true)
let objects = []
//
objectStream.on('data', (obj) => {
if (obj && (obj.name || obj.prefix)) {
this.$snackbar.show({
type: 'bg-success text-white',
message: 'Fetching: ' + obj.name
})
objects.push(obj)
}
})
objectStream.on('end', () => resolve(objects))
objectStream.on('error', (e) => reject(e))
})
// get an objects data
const getObject = (bucket, name) => new Promise((resolve, reject) => {
this.state.host.client.getObject(bucket, name, (err, dataStream) => {
let chunks = []
dataStream.on('data', chunk => {
this.$snackbar.show({
type: 'bg-success text-white',
message: 'Downloading: ' + name
})
chunks.push(chunk)
})
dataStream.on('end', () => resolve(Buffer.concat(chunks || [])))
})
})
// fetch objects info a zip file
const makeZip = (bucket, objects) => new Promise(async(resolve, reject) => {
let zip = new JSZip()
for (let i in objects) {
this.$snackbar.show({
type: 'bg-success text-white',
message: 'Zipping: ' + objects[i].name
})
zip.file(objects[i].name, await getObject(bucket, objects[i].name));
}
zip.generateAsync({
type: "blob"
}).then(content => {
this.$snackbar.show({
type: 'bg-success text-white',
message: 'Zip Created'
})
resolve(content)
})
})
// using FileSaver, download file
const downloadZip = (content) => {
this.$snackbar.show({
type: 'bg-success text-white',
message: `Downloading: ${bucket.name}.zip`
})
FileSaver.saveAs(content, `${bucket.name}.zip`)
}
try {
downloadZip(await makeZip(bucket.name, await objects(bucket.name)))
} catch (e) {
this.$snackbar.show({
type: 'bg-danger text-white',
message: e.message
})
console.error(e)
}
},
如果你想要一个丑陋的方式来下载目录,获取 json 列表然后将一堆 document.createElement('a')
放在 dom 和 a.setAttribute("target", "_blank")
上,但是你将打开一堆“另存为”对话框。