如何在Google Cloud Storage中使用bucket.upload()代替file.createWriteStream()?

时间:2019-04-28 16:25:36

标签: node.js google-cloud-platform google-cloud-storage

在将文件上传到Google Cloud Storage后,我试图获取永久的(未签名的)下载URL。我可以使用file.createWriteStream()获得签名的下载URL,但是file.createWriteStream()不返回包含未签名的下载URL的UploadResponsebucket.upload()包括UploadResponseGet Download URL from file uploaded with Cloud Functions for Firebase有几个答案说明了如何从UploadResponse获取未签名的下载URL。如何将代码中的file.createWriteStream()更改为bucket.upload()?这是我的代码:

const {Storage} = require('@google-cloud/storage');
const storage = new Storage({ projectId: 'my-app' });
const bucket = storage.bucket('my-app.appspot.com');
var file = bucket.file('Audio/' + longLanguage + '/' + pronunciation + '/' + wordFileType);

const config = {
  action: 'read',
  expires: '03-17-2025',
  content_type: 'audio/mp3'
};

function oedPromise() {
  return new Promise(function(resolve, reject) {
    http.get(oedAudioURL, function(response) {
        response.pipe(file.createWriteStream(options))
        .on('error', function(error) {
          console.error(error);
          reject(error);
        })
        .on('finish', function() {
          file.getSignedUrl(config, function(err, url) {
            if (err) {
              console.error(err);
              return;
            } else {
              resolve(url);
            }
          });
        });
      });
    });
  }

我尝试了一下,但是没用:

  function oedPromise() {
    return new Promise(function(resolve, reject) {
      http.get(oedAudioURL, function(response) {
        bucket.upload(response, options)
        .then(function(uploadResponse) {
          console.log('Then do something with UploadResponse.');
        })
        .catch(error => console.error(error));
      });
    });
  }

错误消息为Path must be a string.,换句话说,response是变量,但必须是字符串。

3 个答案:

答案 0 :(得分:2)

我使用 Google Cloud text-to-speech API 来模拟您在做什么。获取文本以从文本文件创建音频文件。创建文件后,我使用 upload 方法将其添加到我的存储桶中,并使用 makePublic 方法获取其公共 URL。我还使用了 node.js 提供的 async/await feature 而不是函数链接(使用 then)来避免“没有这样的对象:...”错误,因为在文件完成上传到存储桶之前执行了 makePublic 方法.

// Imports the Google Cloud client library
const {Storage} = require('@google-cloud/storage');
// Creates a client using Application Default Credentials
const storage = new Storage();
// Imports the Google Cloud client library
const textToSpeech = require('@google-cloud/text-to-speech');
// Get the bucket
const myBucket = storage.bucket('my_bucket');

// Import other required libraries
const fs = require('fs');
const util = require('util');

// Create a client
const client = new textToSpeech.TextToSpeechClient();
    
// Create the variable to save the text to create the audio file
var text = "";

// Function that reads my_text.txt file (which contains the text that will be
// used to create my_audio.mp3) and saves its content in a variable.
function readFile() {
    // This line opens the file as a readable stream
    var readStream = fs.createReadStream('/home/usr/my_text.txt');

    // Read and display the file data on console
    readStream.on('data', function (data) {
        text = data.toString();
    });

    // Execute the createAndUploadFile() fuction until the whole file is read
    readStream.on('end', function (data) {
        createAndUploadFile();
    });
}

// Function that uploads the file to the bucket and generates it public URL.
async function createAndUploadFile() {
    // Construct the request
    const request = {
        input: {text: text},
        // Select the language and SSML voice gender (optional)
        voice: {languageCode: 'en-US', ssmlGender: 'NEUTRAL'},
        // select the type of audio encoding
        audioConfig: {audioEncoding: 'MP3'},
    };

    // Performs the text-to-speech request
    const [response] = await client.synthesizeSpeech(request);
    // Write the binary audio content to a local file
    const writeFile = util.promisify(fs.writeFile);
    await writeFile('my_audio.mp3', response.audioContent, 'binary');
    console.log('Audio content written to file: my_audio.mp3');

    // Wait for the myBucket.upload() function to complete before moving on to the
    // next line to execute it
    let res = await myBucket.upload('/home/usr/my_audio.mp3');
    // If there is an error, it is printed
    if (res.err) { 
        console.log('error'); 
    }
    // If not, the makePublic() fuction is executed
    else { 
        // Get the file in the bucket
        let file = myBucket.file('my_audio.mp3');
        file.makePublic(); 
    }
}


readFile();

答案 1 :(得分:0)

bucket.upload()file.createWriteStream()周围的便捷包装,它采用本地文件系统路径并将文件作为对象上传到存储桶中。

bucket.upload("path/to/local/file.ext", options)
  .then(() => {
    // upload has completed
  });

要生成签名的URL,您需要从存储桶中获取文件对象:

const theFile = bucket.file('file_name');

文件名将是您本地文件的文件名,或者如果您在GCS上为该文件指定了备用远程名称options.destination

然后,使用File.getSignedUrl()获取签名的URL:

bucket.upload("path/to/local/file.ext", options)
  .then(() => {
    const theFile = bucket.file('file.ext');
    return theFile.getSignedURL(signedUrlOptions); // getSignedURL returns a Promise
  })
  .then((signedUrl) => {
    // do something with the signedURL
  });

请参阅:

Bucket.upload() documentation

File.getSignedUrl() documentation

答案 2 :(得分:0)

您可以使用makePublic方法使存储桶中的特定文件公开可读。

从文档中

const {Storage} = require('@google-cloud/storage');
const storage = new Storage();

// 'my-bucket' is your bucket's name
const myBucket = storage.bucket('my-bucket');

// 'my-file' is the path to your file inside your bucket
const file = myBucket.file('my-file');

file.makePublic(function(err, apiResponse) {});

//-
// If the callback is omitted, we'll return a Promise.
//-
file.makePublic().then(function(data) {
  const apiResponse = data[0];
});

现在,URI http://storage.googleapis.com/[BUCKET_NAME]/[OBJECT_NAME]是文件的公共链接,如here所述。

重点是,您只需要此最少的代码即可公开对象,例如使用Cloud Function。然后,您已经知道公共链接的方式了,可以直接在您的应用程序中使用它。