preface

As front end engineers, we work with images on a daily basis. Front-end engineers working on major e-commerce platforms may feel this more clearly.

Here are some of the pitfalls I’ve encountered in dealing with pictures, and I’d like to share my experience with you.

1. Scene representation

When you request an interface with Postman, you get this image (binary)

This image is also returned when viewed in Chrome’s Network (binary)

However, when the debug is printed, garbled characters are returned

Obviously, the type of data has been changed. Thinking about why, the only place it’s possible to change the data type is in Axios.

I went to look at the Axios documentation, and here’s what it says

// `responseType` indicates the type of data that the server will respond with
// options are 'arraybuffer', 'blob', 'document', 'json', 'text', 'stream'
responseType: 'json'.// default
Copy the code

Therefore, the reason for the garble is that axios returns JSON text by default, and binary image data is coerced into JSON text.

Once the cause is found, the solution is easy. So in AXIos, the responseType returns data type json by default, so let’s change that to return data type blob.

export function miniprogramQrcode (params) {
  return axios.post(
    env.MI_URL + '/XXXX/XXX/XXXX',
    params,
    // Change the responseType default json to blob
    {
    responseType: 'blob'.emulateJSON: true
  }).then(res= > {
    if (res.data) {
      return Promise.resolve(res.data)
    } else {
      throw res
    }
  }).catch(err= > {
    return Promise.reject(err)
  })
}
Copy the code

The next question is, what do you do with the BLOB object and display it on the front page?

The code is as follows:

createMiniQrcode (blob) {
  let img = document.createElement('img')
  img.onload = function (e) {
    // The element's onload event destroys the URL object, freeing memory.
    window.URL.revokeObjectURL(img.src)
  }
  // Browsers allow the url.createObjecturl () method to generate a temporary URL for a Blob object.
  // This URL begins with blob://, indicating a blob object.
  img.src = window.URL.createObjectURL(blob)
  document.querySelector('.imgQrCode').appendChild(img)
}
Copy the code

Did you think it was over? No, No, No. It’s not enough to know how to solve a problem, but to think beyond the surface.

Two, divergent thinking

Generally, images can be stored in two ways at the back end:

First: pictures can be stored in the form of independent files in the server's designated folder, and then the path into the database field; The second is to convert the Image into a binary stream and store it directly in the Image type field of the database.Copy the code

For the first storage method, our front end assigns the storage path directly to the SRC property, which can be easily displayed.

For the second storage, our front-end needs to hand over its binary stream to a BLOB object and then use the BLOB API to generate a temporary URL assignment to the SRC attribute for display.

Both storage methods have corresponding solutions, which seem to have solved the problem of picture display perfectly. However, our business scenarios are diverse and fluid. There are times when a drag-and-drop plugin automatically returns a Blob object to you, but unfortunately you find yourself using a third-party service interface that only receives Base64 data.

So, the image of the three forms of URL, base64, blob, three can be transformed to meet the needs? The answer is yes. As follows:

1. Turn base64 url

Url to base64 method encapsulation

// How to use canvas.toDataURL API to convert base64

urlToBase64(url) {
  return new Promise ((resolve,reject) = > {
      let image = new Image();
      image.onload = function() {
        let canvas = document.createElement('canvas');
        canvas.width = this.naturalWidth;
        canvas.height = this.naturalHeight;
        // Insert the image into the canvas and start drawing
        canvas.getContext('2d').drawImage(image, 0.0);
        // result
        let result = canvas.toDataURL('image/png')
        resolve(result);
      };
      / / CORS strategy, problems will cross domain https://stackoverflow.com/questions/20424279/canvas-todataurl-securityerror
      image.setAttribute("crossOrigin".'Anonymous');
      image.src = url;
      // Image load failed error handling
      image.onerror = (a)= > {
        reject(new Error('Picture flow exception'));
    };
}
Copy the code

You can call it like this:

let imgUrL = `http://XXX.jpg`

this.getDataUri(imgUrL).then(res= > {
  // The transformed base64 image address
  console.log('base64', res)
})
Copy the code

2. Turn base64 blob

Base64 to BLOb method encapsulation

CreateObjectURL creates temporary urls for blob objects using url.createObjecturl

base64ToBlob ({b64data = ' ', contentType = ' ', sliceSize = 512{} = {})return new Promise((resolve, reject) = > {
      // Use the atob() method to decode data
      let byteCharacters = atob(b64data);
      let byteArrays = [];
      for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) {
        let slice = byteCharacters.slice(offset, offset + sliceSize);
        let byteNumbers = [];
        for (let i = 0; i < slice.length; i++) {
            byteNumbers.push(slice.charCodeAt(i));
        }
        // A typed array of 8-bit unsigned integer values. The content will be initialized to 0.
        // If the requested number of bytes cannot be allocated, an exception is thrown.
        byteArrays.push(new Uint8Array(byteNumbers));
      }
      let result = new Blob(byteArrays, {
        type: contentType
      })
      result = Object.assign(result,{
        // jartto: be sure to handle the URL. CreateObjectURL
        preview: URL.createObjectURL(result),
        name: 'Image sample. PNG'
      });
      resolve(result)
    })
 }
Copy the code

You can call it like this:

let base64 = base64.split(', ') [1]

this.base64ToBlob({b64data: base64, contentType: 'image/png'}).then(res= > {
    // The blob object after the roll
    console.log('blob', res)
})



Copy the code

3. Turn base64 blob

Blob to Base64 method encapsulation

// How to convert bloB to Base64 using fileReader's readAsDataURL

blobToBase64(blob) {
    return new Promise((resolve, reject) = > {
      const fileReader = new FileReader();
      fileReader.onload = (e) = > {
        resolve(e.target.result);
      };
      // readAsDataURL
      fileReader.readAsDataURL(blob);
      fileReader.onerror = (a)= > {
        reject(new Error('File flow exception'));
      };
    });
}
Copy the code

You can call it like this:

this.blobToBase64(blob).then(res= > {
    // Base64 after conversion
    console.log('base64', res)
})
Copy the code

More url to base64, base64 and bloB conversion demo, will be updated here, interested in poking portal

Ps: The above method is for playing picture stream optimization, thanks to the original author.

Three, the induction of picture processing methods

1. How to store images on the backend

As mentioned earlier, images can be stored in two ways at the back end. Let’s review: First, images can be stored as a separate file in a specified folder on the server, and the path to the database field. Second, the Image is converted into binary stream and stored directly in the Image type field of the database.

So which of these two storage methods is better?

As I understand it, in an Internet environment, high traffic, database speed and performance aspects are important. Generally, the way to store pictures in the database is less, and more is to store the picture path in the database. When showing pictures, you only need to connect the disk path to load the picture in. Because the image belongs to the large field. A picture can range from 1m to several meters. Such large field data will increase the burden of the database, slow down the database. This is important in the case of large concurrent access. This is an experience. Any DBA analysis of database performance tuning will tell you the same thing: don’t store images in the database.

Therefore, if your company’s backend brother often stores images in binary form to the database and then returns them to you for docking, you should know how to dui him (funny face).

For more information on how images or files are stored in the database, please click here

2. Display mode of front end pictures

For the front end: there are three ways to display images in the front end: URL, Base64, and BLOb

Which one is more elegant?

Url: Generally speaking, it is better to use URL for the display of pictures. If the field passed from the back end is the image path.

Base64: If the image is large and the color level of the image is rich, it is not suitable to use this method, because the string encoded in base64 is very large, which will significantly increase the HTML page and affect the loading speed. If images such as loading or table lines are very small and occupy an HTTP request, they will be used in many places. Is very suitable for “Base64 :URL image” technology optimization! Detailed zhang Xinxu’s Demo, please poke here.

Blob: When the back end returns a particular binary stream of images, as described in my scene representation in Part 1, the front end receives it using the BLOB container. It is better to display pictures in blob.

Four, feeling

Give, record, summarize. I will record and sort out the problems encountered in the project bit by bit. I believe that these are scattered branches and leaves. With the increase of project experience, these branches and leaves will eventually grow into a towering tree.

The point of view in this article is limited by my current technical level, it is inevitable that there will be mistakes, welcome to comment on the comment section exchange correction.

With the improvement of technical level, the article will be improved by irregular iteration ~ you can contact me through the following way.

About me

  • My official account (click to enter or scan the QR code below)

  • My Github home page (click to enter)
  • My Nuggets home page (click to enter)
  • My Jane Book home page (click to enter)

Review of articles:

  • An essay writing schedule for 2018

References:

  • ArrayBuffer object, Blob object

  • Axios – API documentation