node.js - 如何从云存储node.js客户端中的url上传文件
问题描述
使用 Google Cloud Storage 版本 1,我成功使用以下功能上传文件。它将文件存储在临时目录中的唯一位置以供进一步处理。
Cloud Storage 版本 4 似乎不再接受 URL 作为源。它会抱怨该文件不存在。
import { File } from "@google-cloud/storage";
import { join, parse } from "path";
import { generate } from "shortid";
import { URL } from "url";
import { getBucket } from "./helpers";
/**
* This function takes a HTTP URL and uploads it to a destination in the bucket
* under the same filename or a generated unique name.
*/
export async function uploadFile(
url: string,
destinationDir: string,
options: { generateUniqueFilename: boolean } = {
generateUniqueFilename: true
}
): Promise<File> {
try {
const pathname = new URL(url).pathname;
const { ext, base } = parse(pathname);
let destination = join(destinationDir, base);
if (options.generateUniqueFilename) {
const shortId = generate();
destination = join(destinationDir, `${shortId}${ext}`);
}
const bucket = await getBucket();
const [file] = await bucket.upload(url, {
destination,
public: true
});
console.log(`Successfully uploaded ${url} to ${destination}`);
return file;
} catch (err) {
throw new Error(
`Failed to upload ${url} to ${destinationDir}: ${err.message}`
);
}
}
使用当前版本如何解决这个问题?我似乎找不到太多关于此的信息。使用 gsutil 不是我的选择。我需要将 URL 传递给 Cloud Function 并从那里上传。
解决方案
这就是我最终的结果:
import { File } from "@google-cloud/storage";
import { join, parse } from "path";
import { generate } from "shortid";
import { URL } from "url";
import { getBucket } from "./helpers";
import * as request from "request";
/**
* This function takes a http url and uploads it to a destination in the bucket
* under the same filename or a generated unique name.
*/
export async function uploadFile(
url: string,
destinationDir: string,
options: { generateUniqueFilename: boolean } = {
generateUniqueFilename: true
}
) {
console.log("Upload file from", url);
const pathname = new URL(url).pathname;
const { ext, base } = parse(pathname);
let destination = join(destinationDir, base);
if (options.generateUniqueFilename) {
const shortId = generate();
destination = join(destinationDir, `${shortId}${ext}`);
}
const bucket = await getBucket();
return new Promise<File>((resolve, reject) => {
const file = bucket.file(destination);
const req = request(url);
req.pause();
req.on("response", res => {
if (res.statusCode !== 200) {
return reject(
new Error(
`Failed to request file from url: ${url}, status code: ${res.statusCode}`
)
);
}
req
.pipe(
file.createWriteStream({
resumable: false,
public: true,
metadata: {
contentType: res.headers["content-type"]
}
})
)
.on("error", err => {
reject(
new Error(
`Failed to upload ${url} to ${destinationDir}: ${err.message}`
)
);
})
.on("finish", () => {
console.log(`Successfully uploaded ${url} to ${destination}`);
resolve(file);
});
req.resume();
});
});
}
推荐阅读
- jquery - 如何根据Datatables jquery中的单元格值禁用行复选框
- html - 如何找出导航的宽度,以便将其设置为与图像完全相同?
- javascript - FirebaseError:Firebase 存储:字符串与格式“base64”不匹配:找到无效字符
- node.js - 在 Heroku 上成功部署我的 node.js 缺少什么
- schema - BizTalk Rule Composer 在添加新词汇后不更新规则
- python - 熊猫从索引中删除字符
- python - Python:Scipy cimport 与 Cython
- reactjs - 将使用 TypeScript 编写的反应组件发布到 npm,但在导入时未定义
- marklogic - 如何在 Marklogic Grove 的 node.js 中处理 REST API?
- node.js - 节点:等到函数完成后再执行 process.exit