MalformedXML:您提供的 XML 格式不正确或未根据我们发布的架构进行验证

Pra*_*gia 21 javascript amazon-s3 amazon-web-services node.js

我在使用 AWS S3 时遇到这个奇怪的问题。我正在开发可以将图像存储到 AWS 存储桶的应用程序。使用 Multer 作为中间件和 S3FS 库连接并上传到 AWS。

但是当我尝试上传内容时,会弹出以下错误。

“MalformedXML:您提供的 XML 格式不正确或未根据我们的发布模式进行验证”

索引.js

var express = require('express');
var router = express();
var multer = require('multer');
var fs = require('fs');
var S3FS = require('s3fs');
var upload = multer({
  dest: 'uploads'
})
var S3fsImpl = new S3FS('bucket-name', {
  region: 'us-east-1',
  accessKeyId: 'XXXXXXXXXXXX',
  secretAccessKey: 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
});

/* GET home page. */
router.get('/', function (req, res, next) {
  res.render('profile', {
    title: 'Express'
  });
});

router.post('/testupload', upload.single('file'), function (req, res) {
  var file = req.file;
  console.log(file);

  var path = req.file.path;
  var stream = fs.createReadStream(path);
  console.log(stream);

  S3fsImpl.writeFile(file.name, stream).then(function () {
    fs.unlink(file.path, function (err) {
      if (err) {
        console.log(err);
      }
    });
    res.redirect('/profile');
  })
});

module.exports = router;
Run Code Online (Sandbox Code Playgroud)

编辑 输出:

{ fieldname: 'file',
  originalname: '441_1.docx',
  encoding: '7bit',
  mimetype: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
  destination: 'uploads',
  filename: '662dcbe544804e4f50dfef1f52b40d22',
  path: 'uploads\\662dcbe544804e4f50dfef1f52b40d22',
  size: 13938 }
ReadStream {
  _readableState:
   ReadableState {
     objectMode: false,
     highWaterMark: 65536,
     buffer: BufferList { head: null, tail: null, length: 0 },
     length: 0,
     pipes: null,
     pipesCount: 0,
     flowing: null,
     ended: false,
     endEmitted: false,
     reading: false,
     sync: true,
     needReadable: false,
     emittedReadable: false,
     readableListening: false,
     resumeScheduled: false,
     defaultEncoding: 'utf8',
     ranOut: false,
     awaitDrain: 0,
     readingMore: false,
     decoder: null,
     encoding: null },
  readable: true,
  domain: null,
  _events: { end: [Function] },
  _eventsCount: 1,
  _maxListeners: undefined,
  path: 'uploads\\662dcbe544804e4f50dfef1f52b40d22',
  fd: null,
  flags: 'r',
  mode: 438,
  start: undefined,
  end: undefined,
  autoClose: true,
  pos: undefined,
  bytesRead: 0 }
Run Code Online (Sandbox Code Playgroud)

包.json

{
  "name": "aws-s3-images",
  "version": "1.0.0",
  "private": true,
  "scripts": {
    "start": "node ./bin/www"
  },
  "dependencies": {
    "body-parser": "~1.17.1",
    "connect-multiparty": "^2.0.0",
    "cookie-parser": "~1.4.3",
    "debug": "~2.6.3",
    "express": "~4.15.2",
    "hbs": "~4.0.1",
    "morgan": "~1.8.1",
    "multer": "^1.3.0",
    "s3fs": "^2.5.0",
    "serve-favicon": "~2.4.2"
  },
  "description": "AWS S3 uploading images",
  "main": "app.js",
  "devDependencies": {},
  "keywords": [
    "javascript"
  ],
  "author": "reeversedev",
  "license": "MIT"
}
Run Code Online (Sandbox Code Playgroud)

小智 21

S3 将每个DeleteObjectsRequest 的文件删除限制为1000。因此,在获取所有 KeyVersions 列表后,我检查键是否 >1000,然后将列表划分为子列表,然后将其传递给带有子列表的 DeleteObjectsRequest,如下所示-

if (keys.size() > 1000) {
            int count = 0;
            List<List> partition = ListUtils.partition(keys, 1000);
            for (List list : partition) {
                count = count + list.size();
                DeleteObjectsRequest request = new DeleteObjectsRequest(
                        fileSystemConfiguration.getTrackingS3BucketName()).withKeys(list);
                amazonS3Client.deleteObjects(request);
                logger.info("Deleted the completed directory files " + list.size() + " from folder "
                        + eventSpecificS3bucket);
            }
            logger.info("Deleted the total directory files " + count + " from folder " + eventSpecificS3bucket);
        } else {
            DeleteObjectsRequest request = new DeleteObjectsRequest(
                    fileSystemConfiguration.getTrackingS3BucketName()).withKeys(keys);
            amazonS3Client.deleteObjects(request);
            logger.info("Deleted the completed directory files from folder " + eventSpecificS3bucket);
        }
Run Code Online (Sandbox Code Playgroud)

  • 这很奇怪。如果您的 DeleteObjectsRequest 超过 1000 个键,则会显示此错误消息。**您提供的 XML 格式不正确,或者未根据我们发布的架构进行验证。** 我认为 AWS SDK 代码存在一些问题。我尝试了这个解决方案,效果很好。 (2认同)

pho*_*gnt 21

我在使用 AmplifyJS 库时遇到这个问题。请按照 AWS 主页中有关分段上传概述的文档进行操作:

每当您上传部分时,Amazon S3 都会在其响应中返回 ETag 标头。对于每个上传的部分,您必须记录部分编号和 ETag 值。您需要在后续请求中包含这些值才能完成分段上传。

但S3默认配置并没有这样做。只需转到“权限”选项卡 -> 添加<ExposeHeader>ETag</ExposeHeader>到 CORS 配置中。 https://github.com/aws-amplify/amplify-js/issues/61

  • 您通过 s3 存储客户端/分段上传的 HTTP 400 问题拯救了我。用更相关的词语进行评论,以便其他可怜的灵魂可以找到:-) (4认同)

Yas*_*eeb 17

因此,如果有人仍然面临这个问题,在我的例子中,只有当您传递要删除的空对象数组时才会发生该问题,它会导致服务器崩溃并出现以下错误“MalformedXML”。

const data: S3.DeleteObjectsRequest = {
  Bucket: bucketName,
  Delete: {
    Objects: [], <<---here
  },
}

return s3Bucket.deleteObjects(data).promise()
Run Code Online (Sandbox Code Playgroud)

因此,只需在将该请求发送到 aws 之前检查键数组是否Objects不等于 0。


小智 -1

这段代码应该适合你。您需要记住:1)使用唯一的存储桶名称2)在文件对象下使用'originalname'而不是'name'<--此属性不存在

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


    var file = req.files[0];

    console.log(file.path);
    console.log(file.name);

    console.log('FIRST TEST: ' + JSON.stringify(file));

    var stream = fs.createReadStream(file.path);    

    S3fsImpl.writeFile(file.originalname, stream).then(function () 
      {
        console.log('File has been sent - OK');
      },
      function(reason)
      {
          throw reason;
      }
     ); 

     res.redirect('/index');   

});
Run Code Online (Sandbox Code Playgroud)