The server uploads the file

The server will transfer the image source to seven Cows, this way the process is

1 the front end will transmit the picture to its own server. 2 The server will transfer the file to seven cows

  • API

The front end

Note that you want to use formData format for file uploads, about formData

document.querySelector('input').onchange = (a)= > {
  const file = document.querySelector('input').files[0]

  let formData = new FormData()
  formData.append('file', file)

  // fetch calls the interface
  fetch(path, {
    body: formData,
    credentials: 'same-origin'.method: 'POST'})}Copy the code

Server Interface

  • The basic parameters
const bucket = 'cancan'
const accessKey = '2LC7KPjwnYdxxxc'
const secretKey = 'SXrxxx'
const domain = 'http://pq3xxxdn.com'
Copy the code
  • Access token
function get_token () {
  const mac = new qiniu.auth.digest.Mac(accessKey, secretKey);
  const policyParams = { scope: bucket }
  const putPolicy = new qiniu.rs.PutPolicy(policyParams);
  const uploadToken = putPolicy.uploadToken(mac);
  return uploadToken
}
Copy the code
  • Upload the file path after you get it
async function uploadFile(localFile, key) {
  const uploadToken = get_token()

  const config = new qiniu.conf.Config();
  // Space corresponding to the machine room
  config.zone = qiniu.zone.Zone_z0;

  const formUploader = new qiniu.form_up.FormUploader(config);
  const putExtra = new qiniu.form_up.PutExtra();

  return new Promise((resolve, reject) = > {
    // File upload
    formUploader.putFile(uploadToken, key, localFile, putExtra, function (respErr, respBody, respInfo) {
      if (respErr) {
        reject('error')}if (respInfo.statusCode == 200) {
        const { key } = respBody
        resolve(`${domain}/${key}`)}}); })}Copy the code
  • interface
router.post('/upload'.async (ctx) => {
  // Get the file information uploaded to the server
  const { img } = ctx.request.files
  // path gets the temporary file address
  const { path } = img

  // key is the name of the image
  const key = Math.random() * 100 + '.png'

  const result = await uploadFile(path, key)

  ctx.body = result
})
Copy the code

Problems encountered

  • The POST interface was never able to resolve to the file parameter

It turns out that the middleware only uses koA-BodyParser, and the general image uploads use Koa-multer. You can use Koa-Body instead of both

Refer to the article

  • Temporary files take up a lot of disk space

As you can see, when the file is uploaded to the server, a temporary file is created – the path that is resolved in the interface

For the server, you can write a timed script to clean up these files. Or we could add a piece of logic to the script to manually delete the temporary file after a successful upload to Qiniu

fs.unlink(path, (err) => {
  if (err) throw err;
  console.log('File deleted', path);
})
Copy the code
  • Git address – server
  • Git address – HTML

Front-end direct upload

The example in the project involves the image uploading, which is to upload the file to the server and then to the seven cow space. This mode of operation is equivalent to making a layer of transfer station in their own server. The developer can do some processing on the image in the transfer station and then upload it to the seven ox space. But there are some disadvantages

  • The memory usage increases

  • Temporary files occupy disk space and need to be deleted after each upload

If you don’t need a transfer station in your development, consider uploading images directly from the front end to Seven Cow Space

Refer to the API documentation of seven Cows, basically can be involved in

  • Generation of upload credentials

  • Front-end file upload

  • area

  • Set upload policy parameters

Obtain the upload certificate token

router.get('/qiniu'.async (ctx, next) => {
  const bucket = 'activity'
  const accessKey = '2LCxxxrxxx'
  const secretKey = 'SXrdqdvxxx'

  const mac = new qiniu.auth.digest.Mac(accessKey, secretKey);
  const policyParams = { scope: bucket }
  const putPolicy = new qiniu.rs.PutPolicy(policyParams);
  const uploadToken = putPolicy.uploadToken(mac);
  ctx.body = uploadToken
})
Copy the code

Front-end upload code

  • Turn base64 blob
    function base64ToBlob(dataurl) { 
      var arr = dataurl.split(', '), 
      mime = arr[0].match(/ : (. *?) ; /) [1], 
      bstr = atob(arr[1]), 
      n = bstr.length, 
      u8arr = new Uint8Array(n); 
      while (n--) { 
        u8arr[n] = bstr.charCodeAt(n); 
      } 
      return new Blob([u8arr], { type: mime }); 
    }
Copy the code
  • The basic parameters
// This token is returned by the server interface
const token = '2LC7KTxxx'

const config = {
  useCdnDomain: true.region: qiniu.region.z1
};

const putExtra = {
  fname: "".params: {},
  mimeType: [] | |null
};

Copy the code
  • Core to upload
const inputTarget = document.querySelector('input')
inputTarget.onchange = (data) = > {
    const imgfile = inputTarget.files[0]
   
    const reader = new FileReader();
    reader.readAsDataURL(imgfile);
    reader.onload = function (e) {
      const urlData = this.result;
      const blobData = base64ToBlob(urlData)
      
      // The first argument here is of the form blob
      const observable = qiniu.upload(blobData, 'filename.png', token, putExtra, config)
      
      const observer = {
        next(res) {console.log(res)},
        error(err) {console.log(err)},
        complete(res) {console.log(res)}
       }
       // Register an observer
      observable.subscribe(observer)
    }
    
}
Copy the code

The file can be sent to the Seven Cows

As you can see, this returns a hash and key. The complete access path at the end of the image is the domain +key configured on your server

If you create a new space in Seven Cows, you will be provided with a free domain name for 30 days

  • Git address – server

  • Git address – HTML

Problems encountered

  • CdnUphost resolution failed

Turned out to be the

 const config = {
    useCdnDomain: true.region: 'qiniu.region.z0'
 }
Copy the code

Region is wrong. It should not be a string, but a variable of seven cows

 const config = {
    useCdnDomain: true.region: qiniu.region.z0
 }
Copy the code

This parameter depends on where your space storage area is selected, right

Select Z0, z1 against the document area

  • The image cannot be read after uploading. The display is corrupted

This is because the first time you upload the input files[0] value, it is not in the format required by the documentation. The documentation requires that this parameter be bloB, so remember to convert the file format here

The previous demo has been written on the failure of shelving, today I ran again, once again ridicule the seven cattle document, write really let head big

Write webpack upload seven cattle plug-in

In development, there is a configuration to use a Webpack, qiniu-webpack-plugin

See how this works and write another upload plugin

Some of the documents involved

  • webpack plugin API

  • webpack plugin config

The plugin to use

    // This is the folder to which the compiled files are compiled
    const filePath = path.resolve(__dirname, 'public')
    
    new QiuniuUploadPlugin({
      bucket,
      accessKey,
      secretKey,
      domain,
      path: filePath
    })
Copy the code

The realization of the class

Much of the logic of this is the same as uploading directly from the back end to seven Cows, so I’ll just write the other part here

  • Outlined implementation
class QiuniuUploadPlugin {
  constructor() {... } uploadQn (filename) {... } apply (compiler) {const pluginName = 'QiuniuUploadPlugin'
    // Event hook
    compiler.hooks.run.tap(pluginName, compilation => {
      console.log("Webpack build process begins!")});// afterEmit - The asynchronous hook tapPromise is fired after the resource is generated to the output directory
    compiler.hooks.afterEmit.tapPromise(pluginName, (compilation) => {
      let { assets } = compilation
      // Assets is an object. Key is the file name. Value is the related parameter
      // assets -->>> { 'index.js' : xxxx }

      // Upload the file through all the file names
      const allUplaod = Object.keys(assets).map((item) = > {
        return this.uplaodQn(item)
      })

      return Promise.all(allUplaod)

    })
  }
}

Copy the code
  • git – webpack

  • Implementation of git-plugin