使用 swagger (v3; yaml) 多方表单数据和 node.js (后端)进行文件上传

using swagger (v3; yaml) multiparty form-data and node.js (backend) for file uploads

问题:为什么这个 node.js 上传文件代码对 jade 有效,但对 swagger 无效?

我一直在尝试弄清楚如何使用 swagger (yaml)、多方、表单数据和 nodejs 上传文件。

我找到了一个关于如何从这个网站上传文件的nodejs代码示例: https://github.com/pillarjs/multiparty/blob/master/examples/azureblobstorage.js

此外,nodejs 项目(类似于上面 github link 中的 nodejs 代码)也可以在这里找到(连同示例项目):

description-of-demo
outdated-but-nice-demo-app

当前端为jade时,nodejs代码按预期工作。然而,form.parser(req) 在使用 swagger api 时似乎失败了。原因似乎是因为数据位于请求中的不同位置。成功时,数据似乎位于 req._readableState.pipes。使用 swagger 时,数据似乎位于 req.swagger.params.

我不知道我是否应该将数据移动到 req._readableState.pipes 或者是否有一个不同的解析器应该用于 swagger 参数(或者其他东西可能被搞砸了)。

// swagger.yaml

  /azureFileTransfer:
    x-swagger-router-controller: azureFilesController
    post:
      operationId: uploadAzureFile
      description: upload azure file
      # ticket info to be stored : schema: $ref: "#/definitions/azureFileData"
      consumes:
        - multipart/form-data
      parameters:
        - name: azureFileDataParam
          description: the file to be uploaded
          in: formData
          required: false
          type: file
      responses:
        "200":
          description: Success
          schema:
            $ref: "#/definitions/GeneralResponse"
        default:
          description: Error
          schema:
            $ref: "#/definitions/ErrorResponse"

// azureFilesController.js(nodejs代码)

module.exports = { uploadAzureFile };
//POST 
function uploadAzureFile(req, res, next) {

  var multiparty = require('multiparty');

  var accessKey = '123456storagepassword';
  var storageAccount = 'myblobstorageName';
  var fs = require('fs');
  var container = 'containerwithinblobstorage';
  var blobService = azure.createBlobService(storageAccount, accessKey);
  var form = new multiparty.Form();

  form.on('part', function (part) {
    if (part.filename) {

      var size = part.byteCount - part.byteOffset;
      var name = part.filename;

      blobService.createBlockBlobFromStream(container, name, part, size, function (error) {
        if (error) {
          res.send(' Blob create: error ');
        }
      });
    } else {
      form.handlePart(part);
    }
  });
  form.parse(req); //req.swagger.params.file.value // req
  res.send('OK');
}

找到解决办法。这可能不是最好的方法……但它是将文件存储到 Azure Blob 存储的一种方法。使用 multer 而不是 multiparty。这是没有任何(最少的)错误检查或加密的基本知识。我也计划研究 multer-azure 和 multer-azure-storage multer-azuremulter-azure-storage

// swagger.yaml(yaml ...后端))

  /azureFileTransfer:
x-swagger-router-controller: azureFilesController
post:
  operationId: uploadAzureFile
  description: upload azure file
  # ticket info to be stored : schema: $ref: "#/definitions/azureFileData"
  consumes:
    - multipart/form-data
  parameters:
    - name: azureFileDataParam
      description: the file to be uploaded
      in: formData
      required: false
      type: file
  responses:
    "200":
      description: Success
      schema:
        $ref: "#/definitions/GeneralResponse"
    default:
      description: Error
      schema:
        $ref: "#/definitions/ErrorResponse"

// azureFilesController.js (nodejs-javascript代码...后端)

module.exports = { uploadAzureFile };

//POST 
function uploadAzureFile(req, res, next) {
  var azureStorage = require('azure-storage');
  var accessKey = 'keyfor_storageAccount';
  var storageAccount = 'azureBlobStorageName';
  var container = 'nameOfContainerInYourBlobStorage'; 
  var blobService = azureStorage.createBlobService(storageAccount, accessKey);

  var file_location = req.files[0].path;
  var file_name = req.files[0].originalname;
  blobService.createBlockBlobFromLocalFile(container, file_name, file_location, function (error, result, response) {
    if (!error) {
      res.sendStatus(200); // file uploaded successfully
    }
    else {
      res.sendStatus(500);
    }
  });
}

// app.js (nodejs-javascript代码...后端)

var multer = require('multer');
app.use(multer({ dest: './uploads/' }).any());

// angularFile.js(angular-javascript代码...前端)

$scope.uploadModel = function () {
  var file = $scope.myFile;
  console.log('file is ');
  console.dir(file);
  var base_uri = $scope.traSettingsService.baseUri;
  var uploadUrl = base_uri + 'azureFileTransfer/'; 
  uploadFileToUrl(file, uploadUrl);
};

function uploadFileToUrl(file, uploadUrl) {
  var testing = null;
  var fd = new FormData();
  fd.append('file', file);
  $http.post(uploadUrl, fd, {
    transformRequest: angular.identity,
    headers: { 'Content-Type': undefined }
  }).then(function successCallback(response) {
    $scope.responseMessage = "Your file was successfully uploaded";
  }, function errorCallback(response) {
    $scope.responseMessage = "The file failed to load. Please try again.";
  });
}