当前位置: 首页 > 知识库问答 >
问题:

上传所有文件后如何回电?

郎慎之
2023-03-14

我需要从远程位置读取所有文件并将它们发送到另一个服务,如果成功发送,则删除所有文件。我的代码对于单个文件工作正常,但如果我想在循环中读取所有文件,那么代码不会被执行。

请按以下方式查找代码。在RemoteFileReadImpl类中,我试图读取循环中不起作用的文件。在WebClientUtil类中,我将文件发送到另一个服务。返回成功响应后,我想重命名已读取的文件。

package com.remotefileread.serviceImpl;

import java.io.IOException;

import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.client.WebClient;

import reactor.core.publisher.Mono;

public class WebClientUtil{

    WebClient webClient = WebClient.create("http://localhost:9091");

    public Mono<HttpStatus> ftpFileSend(MultipartFile fileData) {

        MultiValueMap<String,Object> body=new LinkedMultiValueMap<String,Object>();

        try {
            body.add("file", fileData.getBytes());
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }


        return webClient
                .post()
                .uri("/storeFileData")
                .contentType(MediaType.MULTIPART_FORM_DATA)
                .body(BodyInserters.fromMultipartData(body))
                .exchange()
                .map(response -> {
                    
                    return response.statusCode();
                });
    }
    
}

    package com.remotefileread.serviceImpl;
    
    import java.io.File;
    import java.io.FileInputStream;
    import java.nio.file.Files;
    import java.util.Base64;
    
    import org.apache.commons.io.IOUtils;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.http.HttpStatus;
    import org.springframework.http.MediaType;
    import org.springframework.mock.web.MockMultipartFile;
    import org.springframework.stereotype.Service;
    import org.springframework.web.multipart.MultipartFile;
    import org.springframework.web.reactive.function.server.ServerResponse;
    
    import com.remotefileread.model.SendFileData;
    import com.remotefileread.service.RemoteFileRead;
    
    import reactor.core.publisher.Mono;
    
    @Service
    public class RemoteFileReadImpl implements RemoteFileRead{
    
        @Autowired
        WebClientUtil webClientUtil;
    
        public Mono<ServerResponse> ftpFileRead() { 
            File directoryPath = new File("\\\\localhost\\SharedFolder\\csv_container");
            File files[] = directoryPath.listFiles();
            try {
                for(File csvFile : files) {
                    SendFileData fileData=new SendFileData();   
                    byte[] content = Files.readAllBytes(csvFile.toPath());
    
                    fileData.setFilename(csvFile.getName());
                    fileData.setFileContent(Base64.getEncoder().encodeToString(content));
                    fileData.setCustomerName("Cust");
                    FileInputStream input = new FileInputStream(csvFile);
                    MultipartFile multipartFile = new MockMultipartFile("file",
                            csvFile.getName(),"text/plain",IOUtils.toByteArray(input));
                    input.close();
    
                    Mono<HttpStatus> monoStatus = webClientUtil.ftpFileSend(multipartFile);
    
                    monoStatus
                    .doOnSuccess( httpStatus ->
                    {
                        System.out.println("Http Status:" + httpStatus);
                        
                    })
                    .doOnError(error -> 
                    {
                        System.out.println("Http Status:" + error);
                        
                    });
                }
                return ServerResponse.ok().contentType(MediaType.TEXT_PLAIN).bodyValue("OK");
            }
            catch(Exception ex) {
                return ServerResponse.badRequest().contentType(MediaType.TEXT_PLAIN).bodyValue("Error Message: " + ex.getMessage());
            }
        }
    }

共有1个答案

公西毅
2023-03-14

关于如何改进问题的一些提示:

  • 您提到了每个文件成功时您希望发生的情况,但如果一个文件失败则不会。它应该继续到下一个文件,还是停止并返回服务器错误?
  • 解释它目前的行为,以及它与你的期望/愿望有何不同。
  • 突出显示代码中它不起作用的点。

如果您使用的是reactive,那么您通常不会像现在这样循环。您可能希望创建一个文件流进行处理,作为通量:

Flux.fromArray(directoryPath.listFiles())

接下来,将操作添加到该流的末尾,慢慢构建一个“计划”,说明必须如何处理该流才能产生特定的结果。上面的通量准备好向订阅者逐个生成文件。请注意,在您的代码中,没有任何内容订阅Mono,因此不会启动任何内容。

网络客户端还返回一个新流。flatMap函数允许将流中的元素映射到其他流,然后在原始流中的元素位置进行展平。在您的情况下,web请求只是返回一个Mono。

因此,请记住,将创建多部分文件的代码重构为另一个方法,并使用平面映射通过util类发出web请求,我们将得到以下流:

Flux<HttpStatus> statusStream = 
      Flux.fromArray(directoryPath.listFiles())
          .map(this::createMultipart)
          .flatMap(webClientUtil::ftpFileSend)

现在我们来谈谈WebClient的用法。

请注意,使用exchange(现已弃用)意味着您需要确保使用响应数据,否则可能导致内存泄漏。因此,exchangeToMono()或retrieve()通常更好

如果使用retrieve(),则不成功的响应将自动引发异常,这将在流中导致“错误”信号,从而停止处理任何其他文件。

因此,总体而言,您可以有如下实现:

    public Mono<ResponseEntity<Void>> ftpFileSend(MultipartFile fileData) {

        MultiValueMap<String,Object> body=new LinkedMultiValueMap<String,Object>();

        try {
            body.add("file", fileData.getBytes());
        } catch (IOException e) {
            return Mono.error(e);   // <-- note how to create an error signal
        }


        return webClient
                .post()
                .uri("/storeFileData")
                .contentType(MediaType.MULTIPART_FORM_DATA)
                .body(BodyInserters.fromMultipartData(body))
                .retrieve()
                .toBodilessEntity()
    }

...

    public Mono<ServerResponse> ftpFileRead() { 
    
        return Flux.fromArray(directoryPath.listFiles())
                   .flatMap(this::sendAndRename)
                   .onErrorContinue((ex, file) -> log("failed to process: " + file)) // <-- skips the erroring item and continues
                   .then(Mono.just(
                       ServerResponse.ok()
                             .contentType(MediaType.TEXT_PLAIN)
                             .bodyValue("OK"))
                   .onErrorResume(ex -> Mono.just(
                       ServerResponse.badRequest()
                             .contentType(MediaType.TEXT_PLAIN)
                             .bodyValue("Error Message:" + ex.getMessage())); // <-- not really a need if we just skip.
    }

    public Mono<Void> sendAndRename(final File file) {
        MultipartFile multipart = createMultipart(file);
        return webClientUtil.ftpFileSend(multipart)
                            .then(() -> renameDoneFile(file));
    }

此处发送所有文件。如果发送或重命名时发生错误,将记录该错误,跳过该文件,并继续处理下一个文件。

 类似资料:
  • 今天我想把我的一个项目从我的开发环境转移到我的生产环境。 当我试图通过FTP上传它时,我已经看到几乎110k文件正在更新。 有人能告诉我这是否真的是必需的,或者我是否错过了一些编译功能等来启动和运行它吗? 干杯,费边

  • 问题内容: 我有以下代码来检查(上传的简历和推荐信是否与所需类型(pdf或doc或docx)匹配)和大小(小于400 kb) 这无法正常工作,甚至连txt文件都没有通过+大小限制,这是怎么回事? 谢谢, 问题答案: 下面仅使用mime类型来验证文件,然后检查两者的大小。有关大多数MIME类型的列表,请参见此处或google。

  • 本文向大家介绍C#遍历文件夹后上传文件夹中所有文件错误案例分析,包括了C#遍历文件夹后上传文件夹中所有文件错误案例分析的使用技巧和注意事项,需要的朋友参考一下 asp.net是没有直接选取文件夹的控件的,我也不知道,如果大家有的话可以一起交流下。后来我想着应该有三种方法: ①先将文件夹压缩后上传服务器,然后再服务器上解压; ②获得文件夹名及目录,然后遍历文件夹下面的文件以及子文件夹,循环上传; ③

  • 我正在尝试使用多部分实体方法上传文件。但它失败,错误说{“错误”:“文件参数值'无'无效”} 我的代码是: File File = new File(" C:/Users/SST-06/Desktop/new . txt "); 我的实体文件包含所有提到的参数。 -hkYO-pblk 0 uqlxjtvklrbkosxz 7 mye-8 wbvbvanx Content-Disposition:f

  • 问题内容: 当我查询此问题时,发现了很多帖子,但是它们都涉及如何从浏览器将文件上传到node.js服务器。我想将文件从node.js代码上传到另一台服务器。我试图基于对node.js的有限了解来编写它,但是它不起作用。 上面的函数被其他生成数据的代码调用。 我尝试使用curl -F“ file = @ ”上传相同的数据文件,并且上传成功。但是我的代码失败了。服务器返回一个特定于应用程序的错误,提示

  • 我有这个PHP脚本,它将表单的内容与图像一起上传到数据库。现在,我想让它上传一切,当它被选中(作品),并跳过上传图像部分,上传一切,但图像,如果不是。 下面是在服务器上上传图像的部分。 当我尝试插入没有图像的表单内容时,它会返回: 警告:getimagesize():第14行C:\xampp\htdocs\vinhub\inc\addpost.inc.php中的文件名不能为空 文件不是图像。对不起