preface

Recently, I ran into cross-domain problems using the Element-UI el-Upload component while developing a SpringBoot and Vue based front to back separation project, although I wrote a previous article on solving cross-domain problems. However, it is still unable to solve the cross-domain problem when using action, so this article will be based on the backend SpringBoot and nginx reverse proxy to solve the cross-domain method, the complete code of this article (front-end and back-end code) has been uploaded to GitHub.

useactionThe solution of

Before explaining the details, it should be noted that the back end of this article is based on port 8888, the front end is based on port 8080, and the nginx proxy port 80. Here is the front-end code using El-Upload, with unnecessary attributes removed to focus on cross-domain issues:

<el-upload class="upload-demo" action="http://localhost/nginx/uploadByAction" :file-list="fileList"> <el-button Size ="small" type="primary" </el-button> </el-upload>Copy the code

Here is the back-end configuration file (application.yaml) code:

server:
  port: 8888

upload:
  filePath: D:\\Temp\\img\\
Copy the code

Based on thenginxReverse proxy solution

The back-end interface code is as follows:

@RestController
public class UploadByAction {

    @Value("${upload.filePath}")
    private String filePath;

    @PostMapping("/nginx/uploadByAction")
    public String uploadByNginx(@RequestPart("file") MultipartFile file) {
        return getUploadMsg(file);
    }
    
    private String getUploadMsg(@RequestPart("file") MultipartFile file) {
        if (file.isEmpty()) {
            return "Upload failed, please select file";
        }
        String fileName = file.getOriginalFilename();
        File dest = new File(filePath + fileName);
        try {
            file.transferTo(dest);
            return "Upload successful";
        } catch (IOException e) {
            e.printStackTrace();
            return "Upload failed"; }}}Copy the code

The nginx proxy configuration is as follows:

location / {
	root   html;
	add_header Access-Control-Allow-Origin *;

	if ($request_method = 'OPTIONS') {
		return 204;
	}
	proxy_pass http://localhost:8888;
	index  index.html index.htm;
}
Copy the code

This simple nginx configuration solves the problem of using ation across domains. For those of you who have read the article on how to solve this problem, you will find that the nginx configuration is simply the following:

if ($request_method = 'OPTIONS') {
   return 204;
}
Copy the code

This is because when action is used, a precheck request will be sent. For detailed introduction of the precheck request, you can check this article. The configuration here is mainly for normal return of the precheck request.

Based on theSpringBootBackground code solution

The SpringBoot code solution is to change the nginx reverse proxy configuration to a specific code configuration. First, since reverse proxy is no longer used, El – the action attribute in the upload also need to change to http://localhost:8888/springboot/uploadByAction, and then the background code change:

First, the code for the Controller interface:

@RestController
public class UploadByAction {

    @Value("${upload.filePath}")
    private String filePath;

    @PostMapping("/springboot/uploadByAction")
    public String uploadBySpringBoot(@RequestPart("file") MultipartFile file) {
        return getUploadMsg(file);
    }

    private String getUploadMsg(@RequestPart("file") MultipartFile file) {
        if (file.isEmpty()) {
            return "Upload failed, please select file";
        }
        String fileName = file.getOriginalFilename();
        File dest = new File(filePath + fileName);
        try {
            file.transferTo(dest);
            return "Upload successful";
        } catch (IOException e) {
            e.printStackTrace();
            return "Upload failed"; }}}Copy the code

Then there’s the interceptor setup:

@Configuration
public class CorsInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle( HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        response.addHeader("Access-Control-Allow-Origin"."*");
        if ("OPTIONS".equals(request.getMethod())) {
            return true;
        }
        return HandlerInterceptor.super.preHandle(request, response, handler); }}Copy the code

Finally add interceptors:

@Configuration
public class ApiConfig extends WebMvcConfigurationSupport {

	private final CorsInterceptor corsInterceptor;

	@Autowired
	public ApiConfig(CorsInterceptor corsInterceptor) {
		this.corsInterceptor = corsInterceptor;
	}

	@Override
	protected void addInterceptors(InterceptorRegistry registry) {
		registry.addInterceptor(corsInterceptor).addPathPatterns("/ * *");
		super.addInterceptors(registry); }}Copy the code

After the above configuration, there is no need to use the nginx reverse proxy configuration, and you can directly access port 8888 to request resources.

Do not useactionThe solution of

Here’s a solution to not using action, but it’s still recommended that you don’t use action and have more freedom to handle Ajax requests yourself.

First, the front-end code:

<el-upload class="upload-demo" action="" :http-request="upload"> <el-button size="small" type="primary">  </el-upload>Copy the code

Since action is no longer used, the value here is arbitrary. The http-Request value corresponds to its own method of processing the request. The upload method looks like this (using AXIos to send the Ajax request) :

upload(param) {
  const formData = new FormData()
  formData.append('file', param.file)
  const url = 'http://localhost:8888/uploadWithoutAction'
  axios.post(url, formData).then(data= > {
    console.log('Image uploaded successfully')
  }).catch(response= > {
    console.log('Image upload failed')})}Copy the code

The corresponding controller code for background processing is as follows:

@RestController
public class UploadWithoutAction {

    @Value("${upload.filePath}")
    private String filePath;

    @PostMapping("/uploadWithoutAction")
    public String upload(@RequestPart("file") MultipartFile file) {
        if (file.isEmpty()) {
            return "Upload failed, please select file";
        }
        String fileName = file.getOriginalFilename();
        File dest = new File(filePath + fileName);
        try {
            file.transferTo(dest);
            return "Upload successful";
        } catch (IOException e) {
            e.printStackTrace();
            return "Upload failed"; }}}Copy the code

Response.addheader (” access-Control-allow-Origin “, “*”); response.addheader (” access-Control-allow-Origin “, “*”); If you want to use the nginx reverse proxy to resolve the cross-domain problem, do not set the above interceptor, and then delete the nginx reverse proxy configuration about OPTIONS. Refer to the article dealing with cross-domains in my preface.

conclusion

This article briefly introduces how to deal with the cross-domain problem when using the action of el-Upload. In fact, the nature of the problem is to solve the pre-check request of OPTIONS. Hope to help you.