首页 > 解决方案 > 如何从云存储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 并从那里上传。

标签: node.jsgoogle-cloud-storage

解决方案


这就是我最终的结果:

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


推荐阅读