Multer-s3 在手机上上传空文件

Posted

技术标签:

【中文标题】Multer-s3 在手机上上传空文件【英文标题】:Multer-s3 Uploading empty files on mobile 【发布时间】:2018-08-03 16:47:55 【问题描述】:

我正在使用 Angular 和 multer-s3 将文件从 Angular 应用程序上传到节点服务器。在桌面上一切正常,但由于某种原因,当尝试通过我的 iPhone 7 上传照片时,上传的文件已损坏。我使用相同的图像并在两个设备上运行相同的流程但得到不同的结果所以我假设它是因为移动设备?

这是我尝试在移动设备上打开 S3 文件时收到的警报

The file “1519398514215-test.png” could not be opened because it is empty.

这是我的代码

var aws = require('aws-sdk');
var path = require('path');
var path3 = path.join(__dirname, "../config/config-aws.json");
var multer = require('multer');
var multerS3 = require('multer-s3');
var request = require('request');

aws.config.loadFromPath(path3);
var s3 = new aws.S3();
var fileName = '';
var uploadM = multer(
  storage: multerS3(
    s3: s3,
    bucket: 'XXXX',
    acl: 'public-read',
    metadata: function (req, file, cb) 
      cb(null, fieldName: file.fieldname + '.png');
    ,
    key: function (req, file, cb) 
      fileName =  Date.now().toString() + "-" + file.originalname + '.png' ;
      cb(null, fileName)
    
  )
);



router.post('/', uploadM.array('photos', 3), function(req,res) 
  if (res.error) 
    console.log(error.stack);
    return res.status(400).json(
      message: "Error",
      error: res.error
    );
  
  const url = 'https://s3-us-west-2.amazonaws.com/XXXX/' + fileName;
  return res.status(200).json(
    fileName: url
  );
);

这是我的客户端

sendImage() 
  const formData: FormData = new FormData();

  this.removeObjectFromCanvas('polygon');


  if (!fabric.Canvas.supports('toDataURL')) 
    alert('This browser doesn\'t provide means to serialize canvas to an image');
   else 
    // window.open(this.canvas.toDataURL('png'));
    const image = new Image();
    image.src = this.canvas.toDataURL('png');



        const blob = this.dataURItoBlob(image.src);

        const file = new File([blob], 'test.png');


        formData.append('photos', file, 'test');



        this.postFile(formData);
      


    

    postFile(file) 
      this.fileService.post(file)
      .subscribe(data => 

      , error => 
        console.log(error);
      );
    

更新**********

所以发现您可以在移动设备上进行调试。看起来我发送的缓冲区中有数据。我的第一个想法是缓冲区没有发送。

**** 更新 仍然无法弄清楚这一点。我做了一些研究,它可能与 formData 和 append 有关?但正如您从上面的图片中看到的那样,两者似乎都很好。会继续研究...

***** 更新 肯定是上传空文件。但它只在手机上?

另外,我在发送到节点服务器之前检查了 formData,似乎里面有正确的数据。

***更新

好吧,更奇怪的体验。似乎 multer-s3 正在上传空文件,但是当我在服务器端获取文件并将其返回到客户端,然后读取该文件并显示它时,图像完美显示。所以 formData 不是问题,我假设是 multer-s3 的问题?

****更新 我忘了提到我正在使用fabricjs并从画布中获取图像。我在某些地方读到那里可能存在问题,但就像我上面所说的,当我将文件发送到服务器并将其发送回客户端时,在读取文件后它会完美地显示图像。

****更新 我尝试将 contentType 添加到 multer 方法,现在仅在移动设备上运行时收到 503 服务不可用错误。对于台式机来说很好。

aws.config.loadFromPath(path3);
var file1;
var s3 = new aws.S3();
var fileName = '';
var uploadM = multer(
  storage: multerS3(
    s3: s3,
    bucket: 'rent-z',
    acl: 'public-read',
    contentType: function (req, file, cb) 
      cb(null, 'image/png');
    ,
    metadata: function (req, file, cb) 
      console.log(file);
      cb(null, fieldName: file.fieldname);
    ,
    key: function (req, file, cb) 
      fileName =  Date.now().toString() + "-" + file.originalname;
      file1 = file;
      cb(null, fileName)
    
  )
).array('photos', 1);



router.post('/', function(req,res) 
  uploadM(req, res, function (err) 
    if (err) 
      console.log(err);
      return res.status(400).json(
        message: "Error uploading to multer",
        error: err
      );
    
  console.log('worked');

  if (res.error) 
    console.log(error.stack);
    return res.status(400).json(
      message: "Error",
      error: res.error
    );
  
  // fs.readFile(req.body, function (err, data)  
  const url = 'https://s3-us-west-2.amazonaws.com/rent-z/' + fileName;
  return res.status(200).json(
    fileName: url
  );
  // );
  )

);

我什至尝试运行 multer-s3 的自动查找 mime-type 功能,结果也一样

**** 第 4 天

我开始调试这个问题已经 96 小时了。没有取得任何进展。仍在试图弄清楚为什么它在桌面而不是移动设备上工作。对于任何想要快速总结行为的人:

    用户在桌面上传图片

    用户将图像放在画布上

    使用比例图片

    用户按下sendImage

    这会将图像转换为 dataUri,然后是 blob

    此 blob 已添加到附加到 formData 的文件中

    这个 formData 被发送到 multer-s3 中间件所在的 nodejs 服务器 成功上传文件到s3

    用户在移动设备上试用

    第 7 步失败。文件已上传,但为空。

如果有人对如何继续有任何想法,请告诉我。

【问题讨论】:

有谁知道我可以检查的地方吗?我已经尝试了所有我能想到的。 疯狂猜测(甚至不知道 Multer 是什么):设置正确Content-Type? ***.com/a/21045034/200603 感谢您的提示和实际尝试!不幸的是,我尝试在 multer-s3 中设置 contentType 和同样的问题,在桌面上工作但在移动设备上不工作.. 虽然,现在我在移动设备上收到 503,所以我检查了那个错误。 我无法提供代码,但uploadcare 和filestack 都有免费层。将这些类型的问题传递给 api/service 可以省去很多麻烦。 感谢@kayakinKoder 的建议我现在正在检查uploadcare,因为它似乎最适合我们的需求。绝对是一个可行的选择! 【参考方案1】:

我会将此作为“官方”答案,因为这可能会满足您的需求。每当我遇到这样一个错综复杂的问题时,我的第一个想法通常是“我想知道是否有 API/SaaS/服务可以为我抽象出这个问题。”正如您所发现的,文件上传很棘手,尤其是当您开始投入我们这些天必须处理的无数设备时。

我不会提及任何特定的服务,但谷歌搜索“文件上传 saas”通常会让您成为行业的***玩家。只需 25 - 50 美元/月,您就可以将文件上传抽象为一个非常简单的 api 调用。您现在不仅可以节省时间,而且(假设您选择了可靠的提供商)您将来不会再为文件上传而烦恼。确保文件上传在百万种不同的设备上工作是 SaaS 的工作;确保 S3 集成正常工作是 SaaS 的工作,即使 S3 的 api 发生变化; SaaS 的工作是确保用户在由于某种原因上传失败时看到友好的消息等。我可以花时间为我们的应用程序构建功能,而不是担心文件上传是否在 iPhone 47 上工作。

“但是我与 SaaS 绑定在一起,并按照他们的价格和功能集生活”啊,但你可以尽量减少这个问题。对于我们使用的许多服务,我喜欢制作一个包装器/接口/您想调用的任何名称。在文件上传的情况下,我做了一个ES6模块:fileUploads.js

在这个模块中,我有一个方法upload。这个方法有什么作用?它只是简单地实现和抽象了[fileupload SaaS X]的API。如果将来我们想要或需要从 SaaS X 更改为 SaaS Y,我只需在整个应用程序中更改一件事:我的 fileUpload.js 模块。

【讨论】:

我接触了几家SaaS公司。一旦我整合了一个并解决了我的问题(今天或明天),我将标记为正确! @JonathanCorrin 谢谢,不用担心,有人可能会过来找出你的代码有什么问题。不过,我想:从现在起 2 个月后,当客户告诉我他们不能在他们的黑莓上上传文件时会怎样。我是想花时间尝试自己调试,还是向 [SaaS 公司 X] 提交工单并让他们解决?后者,当然。

以上是关于Multer-s3 在手机上上传空文件的主要内容,如果未能解决你的问题,请参考以下文章

使用 multer-s3 nodejs 将图像上传到亚马逊 s3

md文件怎么打开在手机上

git无法上传空文件夹分析

在github分支上上传空文件夹

调试时文件上传返回空数组

播放框架文件上传空参数