将图片转化为二进制流附在表单中发送出去

时间:2018年11月14日
这是在和媒体对接时遇到的一个问题,不得不说有的媒体是真的变态。
一般情况下媒体对接是比较简单的,就是把我们本地的数据发送给媒体,之后媒体给我们反馈,生成一个m_id,我们拿到这个m_id之后会存在数据库里,这就完成了媒体对接的一半。之后我们通过m_id来查询发送的数据是否通过审核,这也就完成了媒体对接了。
理想的情况如上所示,可是I媒体它跟别人不一样。我们本地的数据一般情况下都有图片或者视频,在对接I媒体时只有图片。之前遇到这种情况都是将图片的链接发送给媒体,因为这些图片都是存储在我们的文件服务器上的。但是I媒体不想要图片链接,希望我们把图片下载好了然后发送过去。
图片总共有5张,还要分两组发送,一组两张一组三张,之后会给我们返回两个m_id。 发送的数据结构如下所示:

const link_1 = [ 'link_1_1', 'link_1_2' ];
const link_2 = [ 'link_2_1', 'link_2_2', 'link_2_3' ]
const all_img_urls: [link_1, link_2] 
const header = {
  a: 'a',
  b: 'b',
}
复制代码

如上所示,all_img_urls中有两个元素,这两个元素是两个数组,里面包含了具体的每条url
这里的处理就比较麻烦了,得先将配置文件解析成两个,再将图片转化为二进制流,之后附在form中发送过去。
关于解析二进制流,本意是想用https请求来获取的,后来发现request也可以将文件转化成二进制流,文档在这里。
关于request的操作其实是比较复杂的,这里我们选择了进阶用法——r.form()。我们将除了二进制流以外的内容放在formheader中,二进制流appendform中。
首先我们需要定义请求配置文件:

const requestOptions = {
  method: httpMethod
  uri: api
  headers: headers
  localPath: url
}
复制代码

之后使用Promise.all生成两个配置文件:

const generateRequsetOption = () => {
  return Promise.all(_.map(all_img_urls, (imgUrls, index) => {
    return {
      method: 'POST',
      uri: api,
      headers: headers,
      imgUrls: imgUrls
    };
  }));
}
复制代码

之所以使用Promise.all是因为下面调用的时候还是需要使用Promise,所以配置文件可以直接是两个Promise对象。
接下来我们需要先将图片地址转化为二进制流,在获取到二进制流之后再进行下一步操作:

generateIqiyiRequsetOption()
.then((options) => {
  Promise.all(_.map(options, (option) => {
    Promise.all(_.map(option.img_urls, (img_url) => {
      new Promise((_resolve, _reject) => {
        request({ uri: imgUrl, encoding: null }, (err, response, body) => {
          if(err){
            return _reject(err)
          }
          return _resolve(body)
        })
      })
    }))
    .then((bodys) => {
      // 下一步操作
    })
  }))
})
复制代码

这里的Promise较多,主要是因为需要处理的东西比较多,首先我们要将两个配置文件循环出来,使用一次Promise.all,之后我们将配置文件中的img_urls循环出来,使用了一次Promise.all,最后我们使用Promise包裹我们请求二进制流的过程,使用了一次Promise。确实比较复杂,但是也没有办法,就这样,我们在.then()中获取的body就是转换之后的二进制流。下面我们使用request来发送数据。

.then((bodys) => {
  return new Promise((_resolve, _reject) => {
    //  定义request的主体内容
    const r = request(_.omit(option, 'img_urls'), (err, response, body) => {
      if(err){
        return _reject(err);
      }
      return _resolve(body);
    })
    const form = r.form();
    _.each(option.img_urls, (img_url, index) => {
      form.append("file_${index}", bodys[index], { filename: img_url.split('/').pop() });
    });
  })
})
复制代码

在获取到二进制流之后我们使用了Promise来处理配置信息,先定义request的主体内容,之后根据配置文件新建form,之后我们循环img_urls,使用index来获取到bodys中的二进制流,还有就是添加一些文件名之类的信息。
至此,我们就完成了数据整合发送到主体内容,全部代码如下所示:

const link_1 = [ 'link_1_1', 'link_1_2' ];
const link_2 = [ 'link_2_1', 'link_2_2', 'link_2_3' ];
const all_img_urls: [link_1, link_2] 
const header = {
  a: 'a',
  b: 'b',
};
const requestOptions = {
  method: httpMethod
  uri: api
  headers: headers
  localPath: url
};
const generateRequsetOption = () => {
  return Promise.all(_.map(all_img_urls, (imgUrls, index) => {
    return {
      method: 'POST',
      uri: api,
      headers: headers,
      imgUrls: imgUrls
    };
  }));
};
return new Promise ((resolve, reject) => {
  generateIqiyiRequsetOption()
  .then((options) => {
    Promise.all(_.map(options, (option) => {
      Promise.all(_.map(option.img_urls, (img_url) => {
        return new Promise((_resolve, _reject) => {
          request({ uri: imgUrl, encoding: null }, (err, response, body) => {
            if(err){
              return _reject(err);
            }
            return _resolve(body);
          });
        });
      }))
      .then((bodys) => {
        return new Promise((_resolve, _reject) => {
          const r = request(_.omit(option, 'img_urls'), (err, response, body) => {
            if(err){
              return _reject(err);
            }
            return _resolve(body);
          });
          const form = r.form();
          _.each(option.img_urls, (img_url, index) => {
            form.append("file_${index}", bodys[index], { filename: img_url.split('/').pop() })
          });
        })
      })
    }))
    .then((results) => {
      //  处理返回数据
    })
  })
});
复制代码

代码其实比较复杂,需要多看看才能理解,主要就是因为请求是异步的,可前端要同时得到反馈,所以只能一层又一层的嵌套Promise,如果有同学有更好的想法可以评论留言,欢迎讨论。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值