vue upload download

Table of contents

upload

download

get

post

object/file stream

download processing return

file stream

axios.post

Package axios

The backend directly returns the file stream, open and download the file as [object Object], just change res to res.data

1. Request setting type responseType: 'blob' (if not set, the open file will be garbled)

2. If there is a request to intercept (just return it directly)

3.download

4. Request a download

related basis

Response.text() gets the text data of the response as a Promise object

decodeURIComponent() decode

escape() encoding

blob

MIME

get and post requests

cache 

Side effect operation, get/display information operation

Content-Disposition 

CORS (Cross-Origin Resource Sharing) cross-origin resource sharing

Require

preflight pre-check

request classification

Simple Request Simple Request (no preflight)

application

When the server does not set cross-domain, json can be disguised as text/plain


upload

submitAddFile(){
            var formData = new FormData();
            formData.append('num', this.addType);
            formData.append('linkId',this.addId);
            formData.append('rfilename',this.addFileName);
            for(var i=0;i<this.addArr.length;i++){
                formData.append('fileUpload',this.addArr[i]);
            }
          let config = {
            headers: {
              'Content-Type': 'multipart/form-data',
              'Authorization': this.token
            }
          };
          this.axios.post(apidate.uploadEnclosure,formData,config)
            .then((response) => {
                if(response.data.info=="success"){this.$message({
                        type: 'success',
                        message: '附件上传成功!'
                    });
                }
            })
        }

Vue realizes the method of file upload and download - Nuggets

download

get

//静态a标签
<a :href='"/user/downloadExcel"' >下载模板</a>

//动态创建a标签:
<div name="downloadfile" onclick="downloadExcel()">下载</div>
function downloadExcel() {
    let a = document.createElement('a')
    a.href ="/user/downloadExcel"
    a.click();
} 

//window
 function downloadExcel() {
    window.location.href = "/tUserHyRights/downloadUsersUrl";
} 

post

object/file stream

download processing return

import axios, { AxiosRequestConfig, AxiosResponse } from 'axios';

export const download= (response: { data?: any; config?: AxiosRequestConfig }) => {
  console.log("response", response);
return new Promise((resolve, reject) => {
  const fileReader = new FileReader();
  fileReader.onload = function () {
    try {
      console.log("result:", this.result);
      const jsonData = JSON.parse((this as any).result); // 成功 说明是普通对象数据
      if (jsonData?.code !== 200) {
        errorMsgTips(jsonData?.message ?? "请求失败");
        reject(jsonData);
      }
    } catch (err) {
      // 解析成对象失败,说明是正常的文件流
      // responseType为blob,以便接收二进制数据。
      const blob = new Blob([response.data]);
      // 本地保存文件
      const url = window.URL.createObjectURL(blob);
      const link = document.createElement("a");
      link.href = url;
      const filename = response?.config.headers?.["content-disposition"]
        ?.split("filename*=")?.[1]
        ?.substr(7);
      link.setAttribute("download", decodeURI(filename));
      document.body.appendChild(link);
      link.click();
      resolve(response.data);
    }
  };
  fileReader.readAsText(response.data);
});

file stream

axios.post

// Vue组件中的方法
methods: {
  downloadFile() {
    axios.post('/api/download', { /* 请求参数 */ }, { responseType: 'blob' })
      .then(response => {
        const url = window.URL.createObjectURL(new Blob([response.data]));
        const link = document.createElement('a');
        link.style.display = 'none'
        link.href = url;
         const filename = response?.config.headers?.["content-disposition"]
           ?.split("filename*=")?.[1]
           ?.substr(7);
         link.setAttribute("download", decodeURI(filename));// 指定下载后的文件名,防跳转
        document.body.appendChild(link);
        link.click();
        document.body.removeChild(link);
      })
      .catch(error => {
        // 处理错误
        console.error(error);
      });
  }
}

Extract the file name from the response header: Content-DispositionThe value of the field of the response header has a form similar to that filename*=UTF-8''example-file.txt, and the file name is extracted example-file.txt.

Package axios

The backend directly returns the file stream , open and download the file as [object Object], just change res to res.data

1. Request setting type responseType: 'blob' (if not set, the open file will be garbled)

import request from '@/utils/request'
import { AxiosRequestConfig, AxiosResponse } from 'axios'
const baseUrl: string = process.env.NODE_ENV === 'development' ? '/test' : ''
const mock: boolean = false

export const postQuery = (params: string): Promise<AxiosResponse> => {
  const url: string = mock ? `${baseUrl}/xxx:8081/otherIndexUpload/${params}` : `${baseUrl}/otherIndexUpload/${params}`
  console.log('post: ', url)
  return request({ url, method: 'post', responseType: 'blob' })
}

return request({
  url: '/data/wos/download',
  method: 'post',
  data: data,
  responseType: 'blob',
  timeout: 3000000,
  onDownloadProgress: function (progressEvent: ProgressEvent<EventTarget>): void {
    // 处理原生进度事件
    store.state.percent = ((progressEvent.loaded / progressEvent.total) * 100).toFixed(2)
    console.log(`下载进度:${store.state.percent}`)
    if (Number(store.state.percent) == 100) {
      store.commit('changeProgress')
    }
  }
})

2. If there is a request to intercept (just return it directly)

import service from 'axios'
import axios, { AxiosRequestConfig, AxiosResponse, AxiosError } from 'axios';

// 响应拦截器
service.interceptors.response.use(
  (response: { data: any; config: AxiosRequestConfig }) => {
    const resData = response.data || {}
    if (response.config.responseType === 'blob') {
      return response
    }..
  },
  (error: AxiosError) => {
...
  }
)

export default service

3.download

export const download = (res: AxiosResponse) => {
  var blob = new Blob([res.data], {
    type: "application/vnd.ms-excel;charset=utf-8",
  });
  var url = window.URL.createObjectURL(blob);
  var aLink = document.createElement("a");
  aLink.style.display = "none";
  //指定文件名,防止跳转
  aLink.download =decodeURIComponent(escape(res?.headers?.["content-disposition"]?.split("filename=")?.[1]))
  aLink.href = url;
  document.body.appendChild(aLink);
  aLink.click();
  document.body.removeChild(aLink);
}

4. Request a download

toDownloadTemplate() {
    console.log('下载模板')
     API.postQuery(`downloadTemplate/${this.wpReleId}`).then((res: any) => {
      if (res.data.type === "application/vnd.ms-excel") {
        download(res);
      } else {
         res.data.text().then((res: any) => {
          this.$message.warning(JSON.parse(res).msg)
         })
       }
    })
  }

related basis

Response.text() gets the text data of the response as a Promise object

Applicable after the responseType is specified in requst, but some content-type of the response is not suitable for the responseType

fetch('https://example.com/api/data')
  .then(response => response.text())
  .then(textData => {
    console.log(textData); // 输出响应的文本数据
  })
  .catch(error => {
    console.error(error);
  });

decodeURIComponent()decoding

The function decodes the encoded string and displays the normal content

escape()coding

The function encodes the garbled string to ensure that special characters (such as Chinese ) are encoded according to UTF-8.

blob

Binary Large Object. Blob is a data type that stores binary data, such as images, audio and video files, etc.

MIME

Multipurpose Internet Mail Extensions indicate the nature and format of the transferred files . Specify a specific string in the HTTP header or other protocols to identify the type of file.

The main type indicates the large category of the file,

"application" indicates the application type,

"text" indicates the text type,

"image" indicates the image type, etc.

A subtype represents a specific file format,

"plain" means plain text,

"vnd" means custom type

"vnd.ms-excel": Microsoft Excel spreadsheet file.

get and post requests

POST: used to transmit information to the server, the function is similar to GET, but it is generally recommended to use POST;

GET: Used to request access to resources identified by URI (Uniform Resource Identifier), which can be passed to the server through the URL;

For GET requests, the browser will send the http header and data together , and the server will respond with 200 (return data);

For POST, the browser sends the header first , the server responds with 100 continue , the browser sends data , and the server responds with 200 ok (return data).

In the case of a good network environment, the difference between the time to send a packet and the time to send two packets can basically be ignored.

In the case of a poor network environment, TCP with two packets has a great advantage in verifying the integrity of the data packet.

Because GET is generally used to query information, POST is generally used to submit certain information for certain modification operations (private information such as registration, login)

So GET will not request again when the browser rolls back , and POST will submit the request again

Because GET will not request again when the browser rolls back , POST will submit the request again

Therefore, GET requests will be actively cached by the browser , and POST will not. If you manually set
       the GET request parameters , they will be completely retained in the browser history, and the parameters in POST will not

Because the parameters of the GET request will be completely retained in the browser history,
the parameters transmitted in the URL of the GET request have a length limit , while POST has no limit

Because GET parameters are passed through the URL , POST is placed in the Request body

So the hyperlink download is a get request

cache 

Side effect operation, get/display information operation

File downloads are a side-effect operation, not regular GET requests for fetching resources.

Browsers usually consider the response of a file download to be one-time and will not be reused.

So even get requests that will be cached by default will not be stored in the cache.

Even if a browser chooses to store file content in the cache, it will usually store it in a temporary cache sessionStorage rather than a long-term persistent cache localStorage.

The file returned by the request is stored in the browser cache, and then downloaded with href, that is, the get request is always moved from the cache to the destination path once.

Because GET will not request again when the browser rolls back , POST will submit the request again

Therefore, the GET request will be actively cached by the browser , so that        the GET request parameters will be completely retained in the browser history if the request is made again , and the parameters in the POST will not

max-age unit: seconds


Because POST requests have side effects (such as modifying data on the server),

Therefore, browsers usually do not cache POST response results, and manually set the cache ( Cache-Control, Expires, Last-Modified, Content-Disposition )

Content-Disposition 

  1. attachment: means to download the content as an attachment.
  2. inline: Indicates to embed the content into the page, usually used to directly display non-HTML content , such as PDF, image, etc.
  3. form-data: Indicates that the response content is a form data, which is usually used in the case of form upload files.

Content-Disposition: attachment; filename="example.pdf"
attachmentmeans to download the response content as an attachment ,

filename="example.pdf"The file name when saving the file is specified as "example.pdf"

Browsers may temporarily store a portion of file data in memory for processing when writing to the destination path.

However, this is not part of the browser cache, but rather temporary storage for file transfers and writes .

CORS (Cross-Origin Resource Sharing) cross-origin resource sharing

Allow browsers to send requests to cross-origin serversXMLHttpRequest , thus overcoming the limitation that  AJAX can only be used on the same origin

It is a fundamental solution to cross-origin AJAX requests , the most commonly used solution

Require

Currently, all browsers support this function, and the IE browser cannot be lower than IE10

CORS requires both browser and backend support. IE 8 and 9 need to implement through XDomainRequest .

CORS can be enabled by setting Access-Control-Allow-Origin on the server side. This attribute indicates which domain names can access resources, and if a wildcard is set, it means that all websites can access resources.

preflight pre-check

A preflight request means that before the browser sends a cross-domain request, it will first send an OPTIONS request to ask the server whether to accept the actual request.

Preflight requests are mainly used for security verification of complex requests, such as those containing custom request headers or using non-simple header fields.

request classification

CORS is divided into simple requests, non-simple/complex requests

Simple Request Simple Request (no preflight)

As long as the following two conditions are met at the same time , it is a simple request

Condition 1: Use one of the following methods:

  • GET
  • HEAD
  • POST

Condition 2: In addition to the allowed custom request headers (for example: X-PINGOTHER), the request header only contains some simple header fields, such as: Accept, Accept-Language, Content-Language, Content-Type, Range.

The value of Content-Type is limited to one of the following three:

  • text/plain
  • multipart/form-data ( key-value pair data)
  • application/x-www-form-urlencoded ( URL encoded) ( default )

The difference between application/xml, text/xml, text/html, and text/plain

1. text/html is the text in  html format

2. text/plain is a plain text (can effectively avoid XSS vulnerabilities)

3. Text/xml ignores the encoding format specified by the xml header and adopts us- ascii encoding by default

4. application/xml will be encoded according to the encoding format specified by the xml header:

None of the XMLHttpRequestUpload objects in the request have any event listeners registered ;

The XMLHttpRequestUpload object can be accessed using the XMLHttpRequest.upload property .

GET /cors? HTTP/1.1
Host: localhost:2333
Connection: keep-alive
Origin: http://localhost:2332
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36
Accept: */*
Referer: http://localhost:2332/CORS.html
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
If-None-Match: W/"1-NWoZK3kTsExUV00Ywo1G5jlUKKs"

Only need to set Access-Control-Allow-Origin on the server side ( indicating that requests for those domain names are accepted (* for all) )

Access-Control-Allow-Origin: http://api.bob.com
Access-Control-Allow-Credentials: true
Access-Control-Expose-Headers: FooBar
Content-Type: text/html; charset=utf-8

Access-Control-Allow-Methods: Specifies the allowed HTTP methods. For example, Access-Control-Allow-Methods: GET, POST, PUTindicates that the GET, POST, and PUT methods are allowed.

Access-Control-Allow-Headers: Specifies the allowed HTTP header fields. For example, Access-Control-Allow-Headers: Content-Type, Authorizationindicates that the Content-Type and Authorization fields are allowed.

Access-Control-Max-Age: Specifies the cache time of preflight requests (OPTIONS requests) to avoid sending preflight requests frequently.

Access-Control-Allow-Credentials: Indicates whether to allow sending credentials (such as cookies) to the target domain. If set to true, it means sending is allowed.

Access-Control-Expose-Headers is a CORS (Cross-Origin Resource Sharing) response header field used to specify additional response header fields that are accessible in cross-origin requests.

Access-Control-Expose-Headers, the server can specify additional response header fields, which will be released by the browser and allow JavaScript code to access.

When a browser initiates a cross-domain request, only some default response header fields (such as Cache-Control, Content-Language, Content-Type, Expires, Last-Modified, Pragma) can be accessed due to security reasons. Other custom response header fields are not accessible by default.

application

When the server does not set cross-domain, json can be disguised as text/plain

principle:

Wrapped as a simple request to bypass pre-checks. But some clients or proxies still pre-check

Safety:

The browser's default handling mechanism for JSON responses is to automatically parse them into JavaScript objects.

When the browser receives the response, if the Content-Type of the response is application/json or no Content-Type is specified , the browser will automatically parse the response body into JSON,  JavaScript objects , and malicious codes may be executed, causing security vulnerability or attack.

By masquerading JSON responses as text/plain, you can avoid the browser's default behavior of automatically parsing responses into JavaScript objects.

In this way, the JavaScript code needs to manually parse the response to ensure the security and correctness of the data. This masquerading provides an additional layer of security against possible security risks from automatic parsing of responses.

//请求头
GET /example HTTP/1.1
Host: example.com
Accept: text/plain
//响应头
HTTP/1.1 200 OK
Content-Type: text/plain
//响应体
{"foo": "bar"}

Cross-Origin Resource Sharing (CORS) - HTTP | MDN

Cross-Origin Resource Sharing (CORS) - HTTP | MDN

Guess you like

Origin blog.csdn.net/qq_28838891/article/details/131443175