欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

基于vue+axios+lrz.js微信端圖片壓縮上傳方法

 更新時間:2019年06月25日 08:22:16   作者:沉淀的風(fēng)  
這篇文章主要介紹了基于vue+axios+lrz.js微信端圖片壓縮上傳方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

業(yè)務(wù)場景

微信端項目是基于Vux + Axios構(gòu)建的,關(guān)于圖片上傳的業(yè)務(wù)場景有以下幾點需求:

1、單張圖片上傳(如個人頭像,實名認(rèn)證等業(yè)務(wù))

2、多張圖片上傳(如某類工單記錄)

3、上傳圖片時期望能按指定尺寸壓縮處理

4、上傳圖片可以從相冊中選擇或者直接拍照

遇到的坑

采用微信JSSDK上傳圖片

在之前開發(fā)的項目中(mui + jquery),有使用過微信JSSDK的接口上傳圖片,本想應(yīng)該能快速遷移至此項目。事實證明編程沒有簡單的事:

1、按指定尺寸壓縮圖片

JSSDK提供的接口wx.chooseImage 是不能指定圖片壓縮尺寸的,只能在后端的接口通過localId獲取圖片時,再轉(zhuǎn)換成指定的尺寸。

2、微信JSSDK的接口權(quán)限驗證

只要是單頁面應(yīng)用項目,微信JSSDK注入權(quán)限驗證都會有這個坑,而這個與路由模式(hash 或 history)也有關(guān)聯(lián)。有關(guān)此坑, 后續(xù)會再次寫文總結(jié)。參考解決方案 [微信JSSDK] 解決SDK注入權(quán)限驗證 安卓正常,IOS出現(xiàn)config fail

經(jīng)過權(quán)衡考慮網(wǎng)頁可能需要在微信以外的瀏覽器上也能上傳文件,顧后來放棄了采用微信JSSDK接口上傳圖片的方式。

android版微信,input onchange事件不觸發(fā)

這個坑,圈內(nèi)有很多人踩過了。在PC端測試是正常的,發(fā)布之后,微信端上傳時能選擇文件,但之后沒有任何效果。日志跟蹤,后臺的api都未調(diào)用,由此判斷是input的onchange事件未被觸發(fā)。

解決方案, 更改input的 accept屬性:

<input ref="file" type="file" accept="image/jpeg,image/png" @change="selectImgs" />

將以上代碼更改為:

<input ref="file" type="file" accept="image/*" @change="selectImgs" />

如果不允許從相冊中選擇,只能拍照,增加capture="camera":

<input ref="file" type="file" accept="image/*" capture="camera" @change="selectImgs" />

(注:如果場景支持從相冊選擇或拍照,測試發(fā)現(xiàn)某些機型拍照后返回到了主頁。哈哈,也有可能是其他因素引起的問題,未做深究了)

使用Lrz.js壓縮圖片

目前手機拍照的圖片文件大小一般在3-4M,如果在上傳時不做壓縮處理會相當(dāng)浪費流量并且占用服務(wù)器的存儲空間(期望上傳原圖的另做討論)。如果能夠在前端壓縮處理,那肯定是最理想的方案。而 lrz.js 則提供了前端圖片文件的壓縮方案,并且可以指定尺寸壓縮。實測:3M左右的圖片文件,按寬度450px尺寸壓縮上傳后的文件大小在500kb左右,上傳時間2s以內(nèi)。

其核心源碼,如下:

selectImgs () {
 let file = this.$refs.file.files[0]
 lrz(file, { width: 450, fieldName: 'file' }).then((rst) => {
  var xhr = new XMLHttpRequest()
  xhr.open('POST', 'http://xxx.com/upload')

  xhr.onload = () => {
   if (xhr.status === 200 || xhr.status === 304) {
    // 無論后端拋出何種錯誤,都會走這里
    try {
     // 如果后端跑異常,則能解析成功, 否則解析不成功
     let resp = JSON.parse(xhr.responseText)
     console.log('response: ', resp)
    } catch (e) {
     this.imageUrl = xhr.responseText
    }
   }
  }

  // 添加參數(shù)
  rst.formData.append('folder', 'wxAvatar') // 保存的文件夾
  rst.formData.append('base64', rst.base64)
  // 觸發(fā)上傳
  xhr.send(rst.formData)

  return rst
 })
}

單個圖片上傳組件完整代碼,如下(注: icon圖標(biāo)使用的是svg-icon組件):

<template>
 <div class="imgUploader">
  <section v-if="imageUrl"
       class="file-item ">
   <img :src="imageUrl"
      alt="">
   <span class="file-remove"
      @click="remove()">+</span>
  </section>
  <section v-else
       class="file-item">
   <div class="add">
    <svg-icon v-if="!text"
         class="icon"
         icon-class="plus" />
    <span v-if="text"
       class="text">{{text}}</span>
    <input type="file"
        accept="image/*"
        @change="selectImgs"
        ref="file">
   </div>
  </section>
 </div>
</template>

<script>
import lrz from 'lrz'
export default {
 props: {
  text: String,
  // 壓縮尺寸,默認(rèn)寬度為450px
  size: {
   type: Number,
   default: 450
  }
 },
 data () {
  return {
   img: {
    name: '',
    src: ''
   },
   uploadUrl: 'http://ff-ff.xxx.cn/UploaderV2/Base64FileUpload',
   imageUrl: ''
  }
 },
 watch: {
  imageUrl (val, oldVal) {
   this.$emit('input', val)
  },
  value (val) {
   this.imageUrl = val
  }
 },
 mounted () {
  this.imageUrl = this.value
 },
 methods: {
  // 選擇圖片
  selectImgs () {
   let file = this.$refs.file.files[0]
   lrz(file, { width: this.size, fieldName: 'file' }).then((rst) => {
    var xhr = new XMLHttpRequest()
    xhr.open('POST', this.uploadUrl)

    xhr.onload = () => {
     if (xhr.status === 200 || xhr.status === 304) {
      // 無論后端拋出何種錯誤,都會走這里
      try {
       // 如果后端跑異常,則能解析成功, 否則解析不成功
       let resp = JSON.parse(xhr.responseText)
       console.log('response: ', resp)
      } catch (e) {
       this.imageUrl = xhr.responseText
      }
     }
    }

    // 添加參數(shù)
    rst.formData.append('folder', this.folder) // 保存的文件夾
    rst.formData.append('base64', rst.base64)
    // 觸發(fā)上傳
    xhr.send(rst.formData)

    return rst
   })
  },
  // 移除圖片
  remove () {
   this.imageUrl = ''
  }
 }
}
</script>

<style lang="less" scoped>
.imgUploader {
 margin-top: 0.5rem;
 .file-item {
  float: left;
  position: relative;
  width: 100px;
  text-align: center;
  left: 2rem;
  img {
   width: 100px;
   height: 100px;
   border: 1px solid #ececec;
  }
  .file-remove {
   position: absolute;
   right: 0px;
   top: 4px;
   width: 14px;
   height: 14px;
   color: white;
   cursor: pointer;
   line-height: 12px;
   border-radius: 100%;
   transform: rotate(45deg);
   background: rgba(0, 0, 0, 0.5);
  }

  &:hover .file-remove {
   display: inline;
  }
  .file-name {
   margin: 0;
   height: 40px;
   word-break: break-all;
   font-size: 14px;
   overflow: hidden;
   text-overflow: ellipsis;
   display: -webkit-box;
   -webkit-line-clamp: 2;
   -webkit-box-orient: vertical;
  }
 }
 .add {
  width: 100px;
  height: 100px;
  float: left;
  text-align: center;
  line-height: 100px;
  font-size: 30px;
  cursor: pointer;
  border: 1px dashed #40c2da;
  color: #40c2da;
  position: relative;
  background: #ffffff;
  .icon {
   font-size: 1.4rem;
   color: #7dd2d9;
   vertical-align: -0.25rem;
  }
  .text {
   font-size: 1.2rem;
   color: #7dd2d9;
   vertical-align: 0.25rem;
  }
 }
}
input[type="file"] {
 position: absolute;
 left: 0;
 top: 0;
 width: 100%;
 height: 100%;
 border: 1px solid #000;
 opacity: 0;
}
</style>

后端圖片存儲處理

后端api對圖片的處理,是必不可少的環(huán)節(jié),需要將前端提交過來的base64字符串轉(zhuǎn)換成圖片格式,并存放至指定的文件夾,接口返回圖片的Url路徑。各項目后端對圖片的處理邏輯都不一致,以下方案僅供參考(我們使用asp.net MVC 構(gòu)建了獨立的文件存儲站點)。

其核心源碼,如下:

/// <summary>
/// 圖片文件base64上傳
/// </summary>
/// <param name="folder">對應(yīng)文件夾位置</param>
/// <param name="base64">圖片文件base64字符串</param>
/// <returns></returns>
public ActionResult Base64FileUpload(string folder, string base64)
{
  var context = System.Web.HttpContext.Current;
  context.Response.ClearContent();
  // 因為前端調(diào)用時,需要做跨域處理
  context.Response.AddHeader("Access-Control-Allow-Origin", "*");
  context.Response.AddHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS");
  context.Response.AddHeader("Access-Control-Allow-Headers", "content-type");
  context.Response.AddHeader("Access-Control-Max-Age", "30");
  if (context.Request.HttpMethod.Equals("OPTIONS"))
  {
    return Content("");
  }

  var resultStr = base64.Substring(base64.IndexOf(",") + 1);//需要去掉頭部信息,這很重要
  byte[] bytes = Convert.FromBase64String(resultStr);
  var fileName = Guid.NewGuid().ToString() + ".png";
  if (folder.IsEmpty()) folder = "folder";
  //本地上傳
  string root = string.Format("/Resource/{0}/", folder);
  string virtualPath = root + fileName;
  string path = Server.MapPath("~" + virtualPath);
  //創(chuàng)建文件夾
  if (!Directory.Exists(Path.GetDirectoryName(path)))
  {
    Directory.CreateDirectory(Path.GetDirectoryName(path));
  }
  System.IO.MemoryStream ms = new System.IO.MemoryStream(bytes);//轉(zhuǎn)換成無法調(diào)整大小的MemoryStream對象
  System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(ms);
  bitmap.Save(path, System.Drawing.Imaging.ImageFormat.Png);//保存到服務(wù)器路徑
  ms.Close();//關(guān)閉當(dāng)前流,并釋放所有與之關(guān)聯(lián)的資源
  return Content(Net.Url + virtualPath); //返回文件路徑
}

結(jié)語

由于項目實際情況,上述的方案中還存在諸多未完善的點:

1、多張圖片上傳,還是采用的與單張圖片相同的接口處理, 更為完善的方案是,前端的多圖上傳組件只綁定一個關(guān)聯(lián)Id,即可通過實現(xiàn)上傳和將圖片列表查詢展示(注:該功能在微信端未實現(xiàn))。

2、后端圖片上傳的接口,未做嚴(yán)格的安全校驗,更為完善的方案是,每個上傳的場景,都應(yīng)該限制文件類型,限制文件大小,以及文件數(shù)據(jù)來源校驗(注: 如軟件需要按二級等保標(biāo)準(zhǔn)測評,則后端接口會檢測通不過)。

3、上傳組件,未顯示上傳進度,體驗性稍差。

正如前文所述,出于項目實際情況考慮,只是簡單實現(xiàn)圖片壓縮上傳功能,如要支持更多的場景,還得細(xì)細(xì)雕琢。

相關(guān)文章

  • Vue組件化通訊的實例代碼

    Vue組件化通訊的實例代碼

    這篇文章主要介紹了Vue組件化通訊的實例代碼的相關(guān)資料,需要的朋友可以參考下
    2017-06-06
  • vue如何關(guān)閉eslint檢測(多種方法)

    vue如何關(guān)閉eslint檢測(多種方法)

    我們在開發(fā)vue項目的時候,創(chuàng)建的時候可能會不小心選擇了eslint,所以如果不想讓eslint檢測,我們該怎么辦呢,本文就詳細(xì)的介紹了幾種關(guān)閉方法,感興趣的可以了解一下
    2021-12-12
  • webpack轉(zhuǎn)vite的詳細(xì)操作流程與問題總結(jié)

    webpack轉(zhuǎn)vite的詳細(xì)操作流程與問題總結(jié)

    Vite是新一代的前端開發(fā)與構(gòu)建工具,相比于傳統(tǒng)的webpack,Vite 有著極速的本地項目啟動速度(通常不超過5s)以及極速的熱更新速度(幾乎無感知),下面這篇文章主要給大家介紹了關(guān)于webpack轉(zhuǎn)vite的詳細(xì)操作流程與問題總結(jié)的相關(guān)資料,需要的朋友可以參考下
    2023-03-03
  • 基于axios封裝fetch方法及調(diào)用實例

    基于axios封裝fetch方法及調(diào)用實例

    下面小編就為大家分享一篇基于axios封裝fetch方法及調(diào)用實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-02-02
  • vue組件 非單文件組件的使用步驟

    vue組件 非單文件組件的使用步驟

    組件又分為非單文件組件和單文件組件,一般常用的就是單文件組件,這篇文章主要介紹了vue組件非單文件組件的使用步驟,需要的朋友可以參考下
    2023-01-01
  • 詳解如何使用Vue-PDF在應(yīng)用中嵌入PDF文檔

    詳解如何使用Vue-PDF在應(yīng)用中嵌入PDF文檔

    在現(xiàn)代Web應(yīng)用中,PDF文檔的使用非常普遍,因為它可以在各種設(shè)備和操作系統(tǒng)上保持一致的外觀和格式,本文我們就來探討一下如何在Vue.js應(yīng)用中使用vue-pdf庫嵌入PDF文檔吧
    2023-08-08
  • vue如何實現(xiàn)本項目頁面之間跳轉(zhuǎn)

    vue如何實現(xiàn)本項目頁面之間跳轉(zhuǎn)

    這篇文章主要介紹了vue如何實現(xiàn)本項目頁面之間跳轉(zhuǎn),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-04-04
  • vue點擊項目唯一id生成器nanoid的使用方式

    vue點擊項目唯一id生成器nanoid的使用方式

    這篇文章主要介紹了vue點擊項目唯一id生成器nanoid的使用方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-05-05
  • vue實現(xiàn)路由不變的情況下,刷新頁面操作示例

    vue實現(xiàn)路由不變的情況下,刷新頁面操作示例

    這篇文章主要介紹了vue實現(xiàn)路由不變的情況下,刷新頁面操作,結(jié)合實例形式分析了vue路由不變的情況下刷新頁面具體原理、操作方法與相關(guān)注意事項,需要的朋友可以參考下
    2020-02-02
  • vue使用@include或@mixin報錯的問題及解決

    vue使用@include或@mixin報錯的問題及解決

    這篇文章主要介紹了vue使用@include或@mixin報錯的問題及解決,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-02-02

最新評論