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