Getting an error "Error: connect ECONNREFUSED 127.0.0.1:80" while sending an image to Backblaze B2

Getting an error "Error: connect ECONNREFUSED 127.0.0.1:80" while sending an image to Backblaze B2

所以我已经尝试将图像上传到 Backblaze B2 存储桶大约三天了。我在获取数据时遇到了困难,但我猜我收到了关于连接拒绝的错误。它 returns 错误代码 504,我尝试通过仅发送图像而不将其转换为 base64 数据来修复它。我不太了解base64数据,所以我认为错误可能是由base64Data引起的。我也没有太多使用 backblaze-b2 的经验,不久前发现了 npm 包“backblaze-b2”。 这是代码:

const B2 = require('backblaze-b2');
const fs = require('fs');

export const uploadImage = async (req, res) => {
  try {
    const b2 = new B2({
      accountId: process.env.BACKBLAZE_ACCOUNT_ID,
      applicationKey: process.env.BACKBLAZE_APPLICATION_MASTER_KEY,
    });

    await b2.authorize();

    // console.log(req.body);

    const { image } = req.body;

    if (!image) return res.status(400).send('No image found!');

    // prepare the image
    const base64Data = new Buffer.from(
      image.replace(/^data:image\/\w+;base64,/,""),
      'base64'
    );

    const handleImage = async () => {
      try {
        let uploadUrl = await b2.getUploadUrl({
          bucketId: process.env.BACKBLAZE_BUCKET_ID,
        });

        // console.log('Is this not working?', uploadUrl);

        const data = b2.uploadFile({
          uploadUrl: uploadUrl.data.bucketId,
          uploadAuthToken: uploadUrl.data.authorizationToken,
          fileName: 'Pepe', //<-- TODO: Fix later
          data: base64Data, // <-- Figure out what to pass in
          onUploadProgress: (e) => null,
        });

        console.log(data);
        res.send(data);
      } catch (err) {
        console.log('Bucket error or something: ', err);
      }
    };

    handleImage();

  } catch (err) {
    console.log(err);
  }
};

这是控制台:

Server is running on port 8000
DB CONNECTED
GET /api/csrf-token 200 2.732 ms - 52
GET /api/current-instructor 304 176.213 ms - -
Bucket error or something:  Error: connect ECONNREFUSED 127.0.0.1:80
    at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1132:16) {
  errno: -4078,
  code: 'ECONNREFUSED',
  syscall: 'connect',
  address: '127.0.0.1',
  port: 80,
  config: {
    url: 'deleted, for safety reasons',
    method: 'post',
    data: <Buffer ff d8 ff e0 00 10 4a 46 49 46 00 01 01 00 00 01 00 01 00 00 ff e2 02 28 49 43 43 5f 50 52 4f 46 
49 4c 45 00 01 01 00 00 02 18 00 00 00 00 02 10 00 00 ... 71126 more bytes>,
    headers: {
      Accept: 'application/json, text/plain, */*',
      'Content-Type': 'b2/x-auto',
      Authorization: 'deleted, for safety reasons',
      'Content-Length': 71176,
      'X-Bz-File-Name': 'Pepe',
      'X-Bz-Content-Sha1': 'deleted, for safety reasons(possibly)',
      'User-Agent': 'axios/0.21.4'
    },
    transformRequest: [ [Function (anonymous)] ],
    transformResponse: [ [Function: transformResponse] ],
    timeout: 0,
    adapter: [Function: httpAdapter],
    xsrfCookieName: 'XSRF-TOKEN',
    xsrfHeaderName: 'X-XSRF-TOKEN',
    onUploadProgress: [Function: onUploadProgress],
    maxContentLength: -1,
    maxBodyLength: -1,
    maxRedirects: 0,
    validateStatus: [Function: validateStatus],
    transitional: {
      silentJSONParsing: true,
      forcedJSONParsing: true,
      clarifyTimeoutError: false
    },
    'axios-retry': { retryCount: 3, lastRequestTime: 1635347528124 }
  },
  request: <ref *1> ClientRequest {
    _events: [Object: null prototype] {
      response: [Function],
      error: [Function: handleRequestError]
    },
    _eventsCount: 2,
    _maxListeners: undefined,
    outputData: [],
    outputSize: 0,
    writable: true,
    destroyed: false,
    _last: true,
    chunkedEncoding: false,
    shouldKeepAlive: false,
    _defaultKeepAlive: true,
    useChunkedEncodingByDefault: true,
    sendDate: false,
    _removedConnection: false,
    _removedContLen: false,
    _removedTE: false,
    _contentLength: 71176,
    _hasBody: true,
    _trailer: '',
    finished: true,
    _headerSent: true,
    _closed: false,
    socket: Socket {
      connecting: false,
      _hadError: true,
      _parent: null,
      _host: 'localhost',
      _readableState: [ReadableState],
      _events: [Object: null prototype],
      _eventsCount: 8,
      _maxListeners: undefined,
      _writableState: [WritableState],
      allowHalfOpen: false,
      _sockname: null,
      _pendingData: [Array],
      _pendingEncoding: '',
      server: null,
      _server: null,
      parser: null,
      _httpMessage: [Circular *1],
      [Symbol(async_id_symbol)]: 325,
      [Symbol(kHandle)]: null,
      [Symbol(kSetNoDelay)]: false,
      [Symbol(lastWriteQueueSize)]: 0,
      [Symbol(timeout)]: null,
      [Symbol(kBuffer)]: null,
      [Symbol(kBufferCb)]: null,
      [Symbol(kBufferGen)]: null,
      [Symbol(kCapture)]: false,
      [Symbol(kBytesRead)]: 0,
      [Symbol(kBytesWritten)]: 0
    },
    _header: 'POST deleted, for safety reasons HTTP/1.1\r\n' +
      'Accept: application/json, text/plain, */*\r\n' +
      'Content-Type: b2/x-auto\r\n' +
      'Authorization: deleted, for safety reasons=\r\n' +        
      'Content-Length: 71176\r\n' +
      'X-Bz-File-Name: Pepe\r\n' +
      'X-Bz-Content-Sha1: deleted, for safety reasons\r\n' +
      'User-Agent: axios/0.21.4\r\n' +
      'Host: localhost\r\n' +
      'Connection: close\r\n' +
      '\r\n',
    _keepAliveTimeout: 0,
    _onPendingData: [Function: nop],
    agent: Agent {
      _events: [Object: null prototype],
      _eventsCount: 2,
      _maxListeners: undefined,
      defaultPort: 80,
      protocol: 'http:',
      options: [Object: null prototype],
      requests: [Object: null prototype] {},
      sockets: [Object: null prototype],
      freeSockets: [Object: null prototype] {},
      keepAliveMsecs: 1000,
      keepAlive: false,
      maxSockets: Infinity,
      maxFreeSockets: 256,
      scheduling: 'lifo',
      maxTotalSockets: Infinity,
      totalSocketCount: 1,
      [Symbol(kCapture)]: false
    },
    socketPath: undefined,
    method: 'POST',
    maxHeaderSize: undefined,
    insecureHTTPParser: undefined,
    path: 'deleted, for safety reasons',
    _ended: false,
    res: null,
    aborted: false,
    timeoutCb: null,
    upgradeOrConnect: false,
    parser: null,
    maxHeadersCount: null,
    reusedSocket: false,
    host: 'localhost',
    protocol: 'http:',
    [Symbol(kCapture)]: false,
    [Symbol(kNeedDrain)]: false,
    [Symbol(corked)]: 0,
    [Symbol(kOutHeaders)]: [Object: null prototype] {
      accept: [Array],
      'content-type': [Array],
      authorization: [Array],
      'content-length': [Array],
      'x-bz-file-name': [Array],
      'x-bz-content-sha1': [Array],
      'user-agent': [Array],
      host: [Array]
    }
  },
  response: undefined,
  isAxiosError: true,
  toJSON: [Function: toJSON]
}

如有任何帮助,我们将不胜感激。 谢谢

我做了一些更改以使其正常工作:

  • 使用 bodyParser.raw() 将正文解析为 backblaze-b2 库期望的 Buffer 格式。它不需要 base64。
  • 将对 b2.uploadFile 的调用中的 uploadUrl.data.bucketId 更正为 uploadUrl.data.uploadUrl.data.uploadUrl。这就是导致 'connection refused' 错误的原因。由于 uploadUrl 不是 URL,我猜测 b2.uploadFile 假定它是一条路径并且您想连接到本地主机。
  • 等待 b2.uploadFile 的响应。
  • 使用 response.data 而不仅仅是 response 来查看 API 响应。

我将您的代码构建到可运行的示例中:

// I like to put my env vars in a .env file
const dotenv = require('dotenv');
dotenv.config();
const B2 = require('backblaze-b2');
const fs = require('fs');

const express = require('express')
const bodyParser = require('body-parser')
const app = express()

const port = process.env.PORT || 3000

const uploadImage = async (req, res) => {
  try {
    const b2 = new B2({
      accountId: process.env.BACKBLAZE_ACCOUNT_ID,
      applicationKey: process.env.BACKBLAZE_APPLICATION_MASTER_KEY,
    });

    await b2.authorize();

    // console.log("req.body:", req.body);

    if (!req.body) return res.status(400).send('No image found!');

    const handleImage = async () => {
      try {
        let uploadUrl = await b2.getUploadUrl({
          bucketId: process.env.BACKBLAZE_BUCKET_ID,
        });

        // Make the JSON more readable
        console.log('getUploadUrl:', JSON.stringify(uploadUrl.data, undefined, 2));

        // uploadFile returns a promise, so we need to await the response
        const response = await b2.uploadFile({
          uploadUrl: uploadUrl.data.uploadUrl,
          uploadAuthToken: uploadUrl.data.authorizationToken,
          fileName: 'Pepe', //<-- TODO: Fix later
          data: req.body, // <-- This is the raw data as a buffer
          onUploadProgress: (e) => null,
        });

        const prettyResponse = JSON.stringify(response.data, undefined, 2);

        console.log('uploadFile: ', prettyResponse);
        res.send(prettyResponse);
      } catch (err) {
        console.log('Bucket error or something: ', err);
      }
    };

    handleImage();

  } catch (err) {
    console.log(err);
  }
};

app.use(bodyParser.raw({ // Raw mode returns the posted body as a Buffer
  type: '*/*' // Parse any mime type
}))

app.post('/', function (req, res) {
  uploadImage(req, res)
})

app.listen(port, () => {
  console.log(`Listening at http://localhost:${port}`)
})

使用 curl 发送文件:

curl http://localhost:3000/ --data-binary @image.png 

控制台输出(有些编辑!):

Listening at http://localhost:3000
getUploadUrl: {
  "authorizationToken": "********",
  "bucketId": "********",
  "uploadUrl": "https://********.backblaze.com/b2api/v2/b2_upload_file/********"
}
uploadFile:  {
  "accountId": "********",
  "action": "upload",
  "bucketId": "********",
  "contentLength": 3802,
  "contentMd5": "d9b8b28f7fda3acfe7838ead41d8df38",
  "contentSha1": "f8040f1068715160ef98ab98fde80f9214cb2845",
  "contentType": "application/octet-stream",
  "fileId": "********",
  "fileInfo": {},
  "fileName": "Pepe",
  "fileRetention": {
    "isClientAuthorizedToRead": true,
    "value": {
      "mode": null,
      "retainUntilTimestamp": null
    }
  },
  "legalHold": {
    "isClientAuthorizedToRead": true,
    "value": null
  },
  "serverSideEncryption": {
    "algorithm": null,
    "mode": null
  },
  "uploadTimestamp": 1641496698000
}