Java 把文件上传到服务器 Nginx

本文介绍了一个使用Java实现的文件上传帮助类,该类利用了Jersey API进行文件的远程上传。具体包括如何将字节数组转换为文件并上传至指定路径,同时确保目标路径存在。此外,还提供了必要的Maven依赖项。

笔记:

更新时间: 2025年5月13日13:43:01

1. 我的环境:JDK 1.8  +  Centos 9 + Nginx 1.2

2. 在 /home 下面创建了一个文件夹: /home/chengdong/upload/images 存放图片

# 创建目录  -p 递归创建目录
mkdir -p /home/chengdong/upload/images

文件夹所属组: 因为我的 nginx 是root用户组,所以 /home/chengdong/upload/images 这个路径也是设置的root组

文件夹的权限:755 确保你要上传文件的目标目录具有正确的权限设置,允许 Nginx 进程进行写入

# 修改权限
sudo chmod -R 755 /home/chengdong/upload/images
# 修改所属组
sudo chown -R root:root /home/chengdong/upload/images

3. 配置 Nginx

http {
    # 设置请求头的最大限制,一定放在http{} 里面,不要放在server
    # 前端request 响应时间也需要修改
    client_max_body_size 100M; # 设置允许上传的最大文件大小

}

# 文件服务器
server {
    listen       80;
    server_name upload.xxxxx.email; # 域名或者ip地址
    # 访问根路径时自动跳转到 /upload
    location = / {
        return 301 /upload;
    }
    location /upload {
        alias /home/chengdong/upload/images/;
        allow all; # 允许所有IP访问
        autoindex on; # 启用目录列表功能,当访问文件夹时显示文件列表
        dav_methods PUT; # 允许put推送
    }
}
# 重启nginx 
sudo systemctl restart nginx

4. Java 代码,添加依赖:有两种手动添加和使用Springboot 集成的

<!-- 文件传输 -->
<!-- Jersey 核心 -->
<dependency>
    <groupId>org.glassfish.jersey.core</groupId>
    <artifactId>jersey-client</artifactId>
    <version>2.39</version>
    </dependency>
<dependency>
<groupId>org.glassfish.jersey.inject</groupId>
    <artifactId>jersey-hk2</artifactId>
    <version>2.39</version>
    </dependency>
    <dependency>
<groupId>org.glassfish.jersey.core</groupId>
    <artifactId>jersey-common</artifactId>
    <version>2.39</version>
</dependency>
<!-- 如果使用 JSON 处理 -->
<dependency>
    <groupId>org.glassfish.jersey.media</groupId>
    <artifactId>jersey-media-json-binding</artifactId>
    <version>2.39</version>
</dependency>


<!-- 如果你使用的是Spring boot 可以只添加下面的即可-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jersey</artifactId>
</dependency>

5. 代码

import org.apache.commons.io.FilenameUtils;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.UUID;

public class Upload {

    public static String Files_Server_Path = "http://upload.xxxxx.email/upload/images/";

    public static void main(String[] args) {
        String filePath = "E:\\3000系列\\3006.png"; // 本地文件路径
        try {
            // 读取本地文件为字节数组
            byte[] fileBytes = Files.readAllBytes(Paths.get(filePath));

            File file = new File(filePath);
            String fileName = file.getName();
            String fileSuffixName = ""; // 文件的后缀名
            if (fileName != null && fileName.lastIndexOf(".") != -1) {
                fileSuffixName = fileName.substring(fileName.lastIndexOf(".") + 1);
            }

            // 调用上传方法
            uploadFile(fileBytes, fileSuffixName);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 将文件推送到 nginx 文件服务器
     * @param fileBytes 文件字节
     * @param fileSuffixName 文件的后缀名
     */
    public static String uploadFile(byte[] fileBytes, String fileSuffixName) {
        String lastFilePath = "";
        Client client = ClientBuilder.newClient();
        try {
            // 将传入的文件后缀名与 UUID 拼接
            String filename = UUID.randomUUID().toString().replace("-", "") + "." + fileSuffixName;

            // 确保文件服务路径不以斜杠结尾
            if (Files_Server_Path.endsWith("/"))
                Files_Server_Path = Files_Server_Path.substring(0, Files_Server_Path.length() - 1);

            WebTarget target = client.target(Files_Server_Path + "/" + filename);

            // 使用PUT方法上传文件
            Response response = target.request()
                    .header("Content-Disposition", "attachment; filename=\"" + filename + "\"")
                    .put(Entity.entity(fileBytes, MediaType.APPLICATION_OCTET_STREAM));

            // 处理响应
            if (response.getStatusInfo().getFamily() == Response.Status.Family.SUCCESSFUL) {
                System.out.println("文件上传成功!");
                System.out.println("上传路径: " + Files_Server_Path + "/" + filename);
                lastFilePath = Files_Server_Path + "/" + filename;
                return lastFilePath;
            } else {
                System.out.println("文件上传失败!状态码: " + response.getStatus());
                System.out.println("错误详情: " + response.readEntity(String.class));
            }
        } finally {
            client.close();
        }
        return lastFilePath;
    }

}

6:执行效果

下面是使用VUE + Spring boot 的一个简单demo 可做参考:

<!--vue html 代码-->
<el-form-item label="商品图片">
	<el-upload ref="uplaod" action="" list-type="picture-card" :on-preview="handlePictureCardPreview"
		:on-remove="handleRemove" :limit="1" :on-change="handleUploadChange" :auto-upload="false">
		<i class="el-icon-plus"></i>
	</el-upload>
	<el-dialog :visible.sync="dialogVisible">
	  <img width="100%" :src="mainImageUrl" alt="">
	</el-dialog>
</el-form-item>


// javaScript 的代码
// 上传商品图片
export function uploadProductImge(data) {
  return request({
    url: '/product/save/upload',
    method: 'post',
    headers: {
        'Content-Type': 'multipart/form-data',
    },
    data: data
  })
}

<script>
import { uploadProductImge } from "@/api/product/save";

export default {
	data() {
		return {
			mainImageUrl: '',
			dialogVisible: false,
			// 省略.....
		}
	},
	methods: {
		handleUploadChange(file, fileList) {
		  const formData = new FormData();
		  formData.append('file', file.raw);

		  uploadProductImge(formData).then(response => {
			console.log(response);
		  }).catch(error => {
			console.error('上传失败:', error);
		  });
		}
	},
	// 上传之后预览
    handlePictureCardPreview(file) {
      this.mainImageUrl = file.url;
      this.dialogVisible = true;
    },
    // 移除
    handleRemove(file, fileList) {
      console.log(file, fileList);
    }
}
</script>

// Controller 后端代码
@PostMapping("/upload")
public AjaxResult upload(@RequestParam("file") MultipartFile file)
{
	if (null == file)
		return error("请选择文件");
	String fileUrl = null;
	try {
		String fileName = file.getOriginalFilename();
        String fileSuffixName = ""; // 文件的后缀名
        if (fileName != null && fileName.lastIndexOf(".") != -1) {
            fileSuffixName = fileName.substring(fileName.lastIndexOf(".") + 1);
        }
        UploadUtils.uploadFile(file.getBytes(), fileSuffixName);
	} catch (Exception e) {
		throw new RuntimeException("文件上传失败");
	}
	return success(fileUrl);
}

}

还有一个简洁版,使用Spring Boot 自带的 RestTemplate, 只需要下面的代码即可

import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import java.util.UUID;

/**
 *	 文件上传帮助类
 * @author chengdong
 * @Date 2025年4月30日11:47:11
 */
@Component
public class UploadUtils {

	private static String serverUploadPath;

	@Value("${server-uplaod-path}")
	public void setServerUploadPath(String path) {
		serverUploadPath = path;
	}

	public static String getServerUploadPath() {
		return serverUploadPath;
	}

	/**
	 * 上传文件到指定服务器路径
	 * @param fileBytes 文件内容的字节数组
	 * @param fileSuffixName 文件后缀名(如:jpg、png等)
	 * @return 文件上传后的完整访问路径(如果上传失败,返回空字符串)
	 */
	public static String uploadFile(byte[] fileBytes, String fileSuffixName) {
		String url = ""; // 最终返回的文件访问路径

		// 1. 生成唯一文件名:UUID去除横杠 + 文件后缀
		String filename = UUID.randomUUID().toString().replace("-", "") + "." + fileSuffixName;

		// 2. 创建RestTemplate实例(Spring提供的HTTP客户端)
		// 注意:实际项目中建议通过@Bean注入,避免重复创建
		RestTemplate restTemplate = new RestTemplate();

		// 3. 设置请求头
		HttpHeaders headers = new HttpHeaders();
		// 设置内容类型为二进制流(适用于任意文件类型)
		headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
		// 设置Content-Disposition告诉服务器这是文件附件
		headers.set("Content-Disposition", "attachment; filename=\"" + filename + "\"");

		// 4. 封装请求实体(包含文件内容和请求头)
		HttpEntity<byte[]> request = new HttpEntity<>(fileBytes, headers);

		// 5. 拼接完整的文件上传URL
		// 注意:serverUploadPath应该是类成员变量,表示服务器存储路径
		url = serverUploadPath + "/" + filename;

		// 6. 执行PUT请求上传文件
		// 问题点:这里直接使用put()方法无法获取响应状态,建议改用exchange()方法
		restTemplate.put(url, request);

		// 7. 返回文件路径(这里无法确认是否真正上传成功)
		return url;
	}
	
}

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

cocosum

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值