从HTTP功能将图像文件写入Firebase存储 [英] Write image file to Firebase Storage from HTTP function

查看:55
本文介绍了从HTTP功能将图像文件写入Firebase存储的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试通过Cloud Function编写映像Firebase存储(以获得更合适的写访问权限).

I am trying to write an image Firebase Storage via a Cloud Function (for more suitable write access).

我当前的尝试是读取客户端上的文件对象,将其(数据)发送到http firebase函数,然后从那里将其保存到存储中.成功保存文件后,我尝试将下载URL用作img src值,但该文件不显示.尝试查看文件时,我还在存储控制台中看到一个错误(加载预览时出错).

My current attempt is to read the file object on the client, send it (the data) to an http firebase function, and then save it to storage from there. After saving the file successfully, I try using the download url as an img src value, but the file does not display. I also see an error in the Storage console (Error loading preview) when attempting to view the file.

如果我将存储中的数据另存为base64,则可以将文件的内容复制到img src属性中,并且可以正常显示.但是,我只想使用下载URL,就像我只是通过客户端SDK或直接通过控制台上传图像一样.

If I save the data in Storage as base64, I can copy the contents of the file into the img src attribute, and it displays fine. However, I'd like to simply use the download URL as I could do if I just uploaded the image via the client SDK or directly via the console.

在客户端中,我只是在使用 FileReader 读取上传的文件进行发送.我已经尝试了所有方法来读取它(readAsTextreadAsBinaryStringreadAsDataURLreadAsArrayBuffer),但似乎没有一个可以解决该问题.

In the client, I'm simply using FileReader to read the uploaded file for sending. I've tried all the ways of reading it (readAsText,readAsBinaryString, readAsDataURL, readAsArrayBuffer), but none seem to solve the issue.

这是我通过Firebase函数上传文件的方式:

Here is how I am uploading the file via the Firebase Function:

import * as functions from 'firebase-functions';
import * as admin from 'firebase-admin';
import * as path from 'path';
import * as os from 'os';
import * as fs from 'fs-extra';

export default functions.https.onCall(async(req, context) => {
  const filename = req.filename;
  const bucket = admin.storage().bucket(environment.bucket)
  const temp_filename = filename;
  const temp_filepath = path.join(os.tmpdir(), temp_filename);
  await fs.outputFile(temp_filepath, req.data, {});

  // Upload.
  await bucket.upload(temp_filepath, {destination: 'logos'})
    .then((val) => {})
    .catch((err) => {});
});

这将成功上传文件,但是,当将其用作img src属性时,下载URL无效.

This uploads the file successfully, however, the Download URL does not work when used as the img src attribute.

我注意到的一件事是,当使用客户端SDK发送文件(通过AngularFireStorage)时,有效载荷是原始png内容.例如.该文件的摘要:

One thing I have noticed is that when using the client SDK to send a file (via AngularFireStorage), the payload is the raw png contents. E.g. a snippet of the file:

PNG


IHDRÈÈ­X®¤IDATx^í]  
Eµ¾·{&1,!dù»*yVQ@PTEDPA>ÊâC\P"ÈÄ"
F}òIW÷üCL@BÉL÷}
....

但是,将文件读取为文本不会产生这种编码.我尝试了其他几种编码.

However, reading the file as text does not yield this encoding. I have tried several other encodings.

任何帮助将不胜感激.

修改

这就是我使用下载URL的意思:

Here is what I mean about using the download URL:

<img alt='logo' src='https://firebasestorage.googleapis.com/v0/b/y<project-name>/o/logos%2FAnM65PlBGluoIzdgN9F5%2Fuser.png?alt=media&token=<token>' />

上面的src网址是单击文件时Firebase存储控制台中提供的网址.它被标记为下载URL"(我相信这是通过sdk调用getDownloadUrl()检索到的URL).

The above src url is the one provided in the Firebase Storage console when clicking on the file. It is labeled as 'Download URL' (I believe this is the one retrieved by calling getDownloadUrl() via the sdk).

使用AngularFireStorage将文件放入存储区时,下载URL将起作用.当我说可以使用"时,是指图像将正确显示.当使用FileReader将数据传递到http云函数进行上传时(如上所示),该图像将不会显示.换句话说,在通过后端上传文件之后,下载URL实际上确实提供了上传的内容,只是没有img标签可以显示的格式.

When using AngularFireStorage to put the file in storage, the Download URL will work. When I say it 'will work', I mean the image will display properly. When using FileReader to pass the data to an http cloud function to upload (as seen above), the image will not display. In other words, after uploading the file via the backend, the download url does in fact provide what was uploaded, it's just not in a format that an img tag can display.

一个可能的问题可能是使用FileReader readAsText时编码不正确.这是我正在使用FileReader进行的操作:

One possible issue may be that I am not getting the encoding correct when using FileReader readAsText. Here is what I am doing with FileReader:

const reader = new FileReader();

reader.onloadend = () => {
  firebase.functions().httpsCallable('http_put_logo')(reader.result);
};

// Have tried various encodings here, as well as all reader methods.
reader.readAsText(file); 

编辑2

到目前为止,有关此问题的所有讨论似乎都围绕正确获取下载URL进行.我不确定Firebase文档是否具有此信息,但是在存储控制台中可以下载URL.目前,我只是将该URL复制并粘贴到其中以进行测试.

All of the discussion on this question so far seems to be around correctly getting the download URL. I'm not sure if Firebase docs have this information, but the download URL is available in the Storage console. I'm simply copying and pasting that URL to for testing purposes at the moment.

之所以这样做,是因为我打算将这些图像URL保存在数据库中,因为它们将被频繁使用和公开读取.因此,我不会使用getDownLoadURL()方法来获取这些图像,我只是直接在img标签中直接链接至它们.

The reason why I am doing this is because I plan to save these image URLs in the DB since they are going to be frequently used and publicly readable. So, I'm not going to use the getDownLoadURL() method to fetch these images, I'm simply just going to link to them directly in img tags.

这是我的控制台的图片,以了解我的意思(右下):

Here is an image of my console to see what I mean (bottom right):

您只需要单击并复制它.然后,您可以在浏览器选项卡中将其打开,下载,将其用作src值等.

You just have to click it and copy it. You can then open it in a browser tab, download it, use it as a src value, etc.

编辑3

以下是使用客户端sdk时请求有效负载的外观图像:

Here is an image of what the request payload looks like when using the client sdk:

这是当我以文本形式读取文件并发送到后端进行上传时:

Here is when I read the file as text and send to backend for upload:

请注意,有效负载有所不同.这就是为什么我不确定是否正确读取文件或编码错误的原因.

Notice there are differences in the payloads. That's why I'm uncertain if I'm properly reading the file or encoding it incorrectly.

推荐答案

您的代码的哪一部分负责获取URL?我最近使用一种类似的方法,使用云功能将图像上传到Firebase Storage.对我而言,最有效的方法是在上传完成后执行其他功能以获取URL.像这样:

What part of your code is taking care of getting the URL? I recently used a similar approach to uploading images to Firebase Storage using cloud functions. What worked best for me was to execute a different function to get the URL after the upload is complete. Something like this:

const bucket = admin.storage().bucket(environment.bucket)
  const temp_filename = filename;
  const temp_filepath = path.join(os.tmpdir(), temp_filename);
  await fs.outputFile(temp_filepath, req.data, {});

  // Upload.
  await bucket.upload(temp_filepath, {destination: 'images'})
    .then((val) => {retrieveUrl(temp_filename)})
    .catch((err) => {});

retrieveUrl = (imageName) => {
    const storage = firebase.storage();
    storage.ref(`/images/${imageName}.jpg`).getDownloadURL()
      .then( url => {
        /*Save the url to a variable or attach it directly to the src of your image, depending on the structure of your project*/
      })
      .catch(err => console.log(err));
  }

请记住,您需要在项目中安装firebase才能调用firebase.storage.

Keep in mind that you need to install firebase in your project in order to call firebase.storage.

这篇关于从HTTP功能将图像文件写入Firebase存储的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆