Java 我需要帮助将spring MVC中的多部分文件保存到SMB网络驱动器

Java 我需要帮助将spring MVC中的多部分文件保存到SMB网络驱动器,java,spring,spring-boot,spring-mvc,Java,Spring,Spring Boot,Spring Mvc,我试图将一个多部分文件(上传到SpringMVC控制器)保存到网络上的linux服务器(需要身份验证)。我尝试使用jcifs实现smb,但性能非常差 有人能告诉我另一种方法吗?我到处搜索了两天,都没能找到一个有效的解决方案 应用服务器运行linux 编辑:这是我正在使用的代码。代码可以工作,但执行得非常非常糟糕 import java.io.File; import java.io.IOException; import java.io.InputStream; import java.nio.

我试图将一个多部分文件(上传到SpringMVC控制器)保存到网络上的linux服务器(需要身份验证)。我尝试使用jcifs实现smb,但性能非常差

有人能告诉我另一种方法吗?我到处搜索了两天,都没能找到一个有效的解决方案

应用服务器运行linux

编辑:这是我正在使用的代码。代码可以工作,但执行得非常非常糟糕

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import jcifs.smb.NtlmPasswordAuthentication;
import jcifs.smb.SmbFile;
import jcifs.smb.SmbFileInputStream;
import jcifs.smb.SmbFileOutputStream;

@Component
public class FileUploadUtil {

    private static final Logger LOGGER = LoggerFactory.getLogger(FileUploadUtil.class);

    @Value("${dr.fileuser}")
    private String user;

    @Value("${dr.filepwd}")
    private String pass;

    @Value("${dr.sharePath}")
    private String drSharePath;

    @Value("${dr.fileLocation}")
    private String drFileLocation;

    @Value("${dr.serverName}")
    private String drServerName;


    /**
     * @param uploadedFile
     * @param filename
     * @param discId: this is a generated id, used to associate these files with a database record.
     * @return
     * @throws WW_Exception
     * @throws IOException
     */
    public String writeFileToServer(MultipartFile uploadedFile, String filename, Integer discId) throws WW_Exception, IOException   {

        NtlmPasswordAuthentication auth = new NtlmPasswordAuthentication("",user, pass);

        String destDir = StringUtils.cleanPath("smb://" + drServerName + drSharePath + drFileLocation + discId + "/");

        LOGGER.info("FILE Destination DIR: {}", destDir);
        try{
            //create directory structure
            SmbFile sfileDir = new SmbFile(destDir, auth);
            if(!sfileDir.exists()) {
                sfileDir.mkdirs();
            }

            String destFilePath = StringUtils.cleanPath(destDir + filename);
            LOGGER.info("FILE Destination PATH: {}", destFilePath);
            SmbFile sfile = new SmbFile(destFilePath, auth);
            try (SmbFileOutputStream fos = new SmbFileOutputStream(sfile)){
                fos.write(uploadedFile.getBytes());
            }

            return destFilePath.replace("smb:", "");

        } catch(Exception e){
            throw e;
        }

    }

    /**
     * @param drId: this is a generated id, used to associate these files with a database record.
     * @param origFilePath
     * @return
     * @throws IOException
     */
    public String copyFileFromServer(Integer drId, String origFilePath) throws  IOException   {

        LOGGER.info("FILE to get: {}",origFilePath);

        NtlmPasswordAuthentication auth = new NtlmPasswordAuthentication("",user, pass);

        String[] imagePathInfo = origFilePath.split("/");
        String destFilePath = StringUtils.cleanPath("/weblogs/tmp/" + drId + "/" + imagePathInfo[imagePathInfo.length-1]);

        File destDir = new File(StringUtils.cleanPath("/weblogs/tmp/" + drId + "/"));
        if(!destDir.exists()) {
            destDir.mkdirs();
        }

        SmbFile origFile = new SmbFile(origFilePath,auth);
        try(InputStream in = new SmbFileInputStream(origFile)) {
             Files.copy(in, Paths.get(destFilePath), StandardCopyOption.REPLACE_EXISTING);
        }

        return destFilePath;

    }
}

请检查您试图保存多部分文件的位置,该文件具有linux机器的读写权限。

@Jorge

根据您在上面的评论,因为您拥有linux服务器的root访问权限,所以我认为您所需要做的只是常规的旧内核装载。您需要确保已安装cifs客户端(假设为ubuntu):

然后,您应该能够通过以下方式装载您的共享:

$ SMB_USERNAME=<your username>
$ SMB_PASSWORD=<your password>
$ SMB_SERVER="//<your host>/<your share>"
$ sudo mount -t cifs -o username=${SMB_USERNAME},password=${SMB_PASSWORD} \
       "${SMB_SERVER}" /mnt
StoreConfig.java

FileStore.java

@StoreRestResource(path=“files”)
公共接口文件存储扩展存储{
}
就这样。文件存储本质上是一个通用的Spring ResourceLoader。
spring-content-fs
依赖项将导致spring-content注入一个基于文件系统的实现,因此您无需担心自己实现它。此外,如果
@Controller
将HTTP请求转发到
文件存储
的方法上,则
spring-content-rest
依赖项将导致spring-content也注入一个实现

因此,您现在将在
/files
上拥有一个功能齐全的(POST、PUT、GET、DELETE)基于REST的文件服务,该服务将使用
文件存储
/mnt
中检索(和存储)文件;i、 e.在远程SMB服务器上

因此:

GET/files/some/file.csv

将从
/path/to/your/files/some/
下载
file.csv

而且

curl——上传文件some-other-file.csv/files/some-other-file.csv

将上载
其他一些文件.csv
,并将其存储在服务器上的
/mnt/

以及:

curl/files/some other file.csv

我将再次检索它


注入的控制器也支持视频流,以防有用。

Hi@Jorge,您是否有问题服务器的root访问权限?另外,你是想把这些上传的内容与Spring数据实体或类似的东西联系起来,还是只是把文件存储在服务器上的一个已知路径上,以便以后检索?嗨@PaulWarren,我可以获得服务器的root访问权限。我只是想保存这个文件以便以后检索。现在使用jcifs存储8MB文件需要大约8秒的时间,这个文件太长了。非常感谢。嗨@iragond,我刚刚更新了帖子。代码没有失败,只是性能很差。谢谢,@PaulWarren。。。我将尝试一下并发布结果。有没有办法在使用Spring内容上传文件时指定一个子目录?我们所做的一些上传是基于行id的,需要将所有相关文件放在同一子目录下。@Jorge,是的。如果您上载到
/files/a/b/some-other-file.csv
,则它将存储在“`/mnt/a/b/some-other-file.csv”中`
$ SMB_USERNAME=<your username>
$ SMB_PASSWORD=<your password>
$ SMB_SERVER="//<your host>/<your share>"
$ sudo mount -t cifs -o username=${SMB_USERNAME},password=${SMB_PASSWORD} \
       "${SMB_SERVER}" /mnt
    <!-- Java API -->
    <!-- just change this depdendency if you want to store somewhere else -->
    <dependency>
        <groupId>com.github.paulcwarren</groupId>
        <artifactId>spring-content-fs</artifactId>
        <version>0.7.0</version>
    </dependency>
    <!-- REST API -->
    <dependency>
        <groupId>com.github.paulcwarren</groupId>
        <artifactId>spring-content-rest</artifactId>
        <version>0.7.0</version>
    </dependency>
@Configuration
@EnableFilesystemStores
@Import(RestConfiguration.class)
public class StoreConfig {

    @Bean
    FileSystemResourceLoader fileSystemResourceLoader() throws IOException {
        return new FileSystemResourceLoader(new File("/mnt").getAbsolutePath());
    }

}
  @StoreRestResource(path="files")
  public interface FileStore extends Store<String> {
  }