简体   繁体   English

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

[英]MalformedXML: The XML you provided was not well-formed or did not validate against our published schema

I am having this weird issue while working with AWS S3.我在使用 AWS S3 时遇到了这个奇怪的问题。 I am working on application by which I can store the images to AWS bucket.我正在开发可以将图像存储到 AWS 存储桶的应用程序。 Using Multer as middleware and S3FS library to connect and upload to AWS.使用 Multer 作为中间件和 S3FS 库连接并上传到 AWS。

But the following error pops up when I try uploading the content.但是当我尝试上传内容时弹出以下错误。

"MalformedXML: The XML you provided was not well-formed or did not validate against our publis hed schema" “格式错误的 XML:您提供的 XML 格式不正确或未根据我们发布的架构进行验证”

Index.js索引.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;

EDIT Output:编辑Output:

{ 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 }

Package.json Package.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"
}

So if anyone still facing this issue, in my case the issue only happens when you pass an empty array of objects you wanna delete, it causes the server to crash with the following error "MalformedXML".因此,如果有人仍然面临这个问题,在我的例子中,这个问题只会在你传递一个你想删除的空对象数组时发生,它会导致服务器崩溃并出现以下错误“MalformedXML”。

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

return s3Bucket.deleteObjects(data).promise()

so just check if the array of Objects keys isn't equal to zero before sending that request to aws.因此,在将该请求发送到 aws 之前,只需检查Objects键数组是否不等于零。

The S3 restricts the file deletion 1000 per DeleteObjectsRequest. S3 将每个 DeleteObjectsRequest 的文件删除限制为 1000。 Hence after fetching all KeyVersions List, I gave the check if the keys are >1000, then partition the list into sublists and then pass it to the DeleteObjectsRequest with sublists as below-因此,在获取所有 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);
        }

I got this problem when use AmplifyJS library.我在使用 AmplifyJS 库时遇到了这个问题。 Follow the document in AWS homepage about Multipart upload overview :按照 AWS 主页中有关分段上传概述的文档进行操作:

Whenever you upload a part, Amazon S3 returns an ETag header in its response.每当您上传一个部分时,Amazon S3 都会在其响应中返回一个 ETag 标头。 For each part upload, you must record the part number and the ETag value.对于每个分段上传,您必须记录分段编号和 ETag 值。 You need to include these values in the subsequent request to complete the multipart upload.您需要在后续请求中包含这些值才能完成分段上传。

But S3 default config does not do it.但是 S3 默认配置不这样做。 Just go To Permissions tab -> Add <ExposeHeader>ETag</ExposeHeader> into CORS Configuration.只需转到权限选项卡 -> 将<ExposeHeader>ETag</ExposeHeader>到 CORS 配置中。 https://github.com/aws-amplify/amplify-js/issues/61 https://github.com/aws-amplify/amplify-js/issues/61

This code should work for you.这段代码应该适合你。 You need to remember that: 1) use unique bucket name 2) under your file object use 'originalname' instead of 'name' <-- this property does not exist您需要记住: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');   

});

据我所知,只需交叉检查 BUCKET NAME。

final PutObjectRequest putObjectRequest = new PutObjectRequest(**bucketName**, accessKeyId, is ,meta); 

If you use ActiveStorage with Minio add force_path_style: true to your config如果您将 ActiveStorage 与 Minio 一起使用,请将force_path_style: true添加到您的配置中

# config/storage.yml
minio:
   service: S3
   access_key_id: name
   secret_access_key: password
   endpoint: http://example.com:9000/
   region: us-east-1
   bucket: myapp-production
   force_path_style: true # add this
input := &s3.DeleteObjectsInput{
        Bucket: bucketName,
        Delete: &s3.Delete{Objects: objs, // <-  up to 1000 keys
       Quiet: aws.Bool(false)},
    }

I am using aws-sdk-go sdk, when the num of the key in objs is overer 1000,I have get the same error like: MalformedXML: The XML you provided was not well-formed or did not validate against our published schema.我正在使用 aws-sdk-go sdk,当 objs 中的键数超过 1000 时,我得到了同样的错误,如:MalformedXML: The XML you provide is not well-formed or did not verify against our published schema。

The request contains a list of up to 1000 keys.该请求包含最多 1000 个键的列表。 reference: https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteObjects.html参考: https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteObjects.html

For those which came here from talend, In my case cross check the tS3Put component's Bucket name and in the key part give any name which you want to see in the s3 as a uploaded file.对于那些来自 talend 的人,在我的例子中,交叉检查 tS3Put 组件的 Bucket 名称,并在关键部分给出您希望在 s3 中看到的任何名称作为上传文件。

As I'm new to StackOverflow, I'm not allowed to attached images here.由于我是 StackOverflow 的新手,因此不允许在此处附加图片。 You can copy the below url to check it out.您可以复制以下url查看。 Thanks谢谢

https://i.stack.imgur.com/Q1pW0.png https://i.stack.imgur.com/Q1pW0.png

Can you try this code:你能试试这个代码吗:

var S3fsImpl = new S3FS('bucket-name', {
  region: 'us-east-1',
  accessKeyId: 'XXXXXXXXXXXX',
  secretAccessKey: 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
});

var fsImplStyles = S3fsImpl.getPath(file.name);

// Change us-east-1 for your region
var url = 'https://s3-us-east-1.amazonaws.com/' + fsImplStyles;

Send feedback, if this code works for you.如果此代码适合您,请发送反馈。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM