以下是介绍有关上传图片所涉及的http.header,如果小伙伴有兴趣了解更多的http的信息,可以点击最下面的腾讯云社区链接。
下载图片
下载图片所涉及的http.header主要有四个,分别为Content-Disposition,Content-Type, Content-length, Connection。
Content-Disposition
响应标头是指示内容是否预期在浏览器中内联显示的标题,即,作为网页或作为网页的一部分或作为附件下载并且本地保存。
Content-Disposition有两个值。
Content-Disposition:inline(默认值,表示它可以显示在网页内,或作为网页)
Content-Disposition:attachment(表示它应该下载)
这里主要讲 attachment
大多数浏览器下载图片呈现“另存为”对话框,预先填入filename如果存在参数的值。
Content-Disposition:attachment;filename="filename.jpg"
Content-Type
Content-Type实体头用于指示所述媒体类型的资源的,如果是图片的话,类型有image/jpeg, image/png, image/gif等等。
Content-Type:image/jpeg
Content-length
Content-Length实体报头指示该实体主体的大小,以字节为单位的十进制数,发送到接收方。
Content-length:1024
Connection
一般 header 控制网络连接是否保持打开状态,当前事务结束之后。如果发送的值是keep-alive,连接是持久的并且不关闭,从而允许对同一服务器的后续请求完成。
一般下载图片都是设置在下载完后就关闭。
Connection:close
在线显示文件
和上面大体相同,就是这里不一样
Content-Disposition:filename="filename.jpg"
就是在Content-Disposition不需要填入attachment。
下面直接上代码
package com.lijun.spring.boot.domain;
import org.bson.types.Binary;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
import java.util.Date;
import java.util.Objects;
@Document
public class File {
@Id
private String id;
private String name; //文件名称
private String contentType; //文件类型
private Long size; //文件大小
private Date uploadDate; //上传时间
private String md5; //计算文件MD5,判断文件是否相同
private Binary content; //文件内容
private String path; //文件路径
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getContentType() {
return contentType;
}
public void setContentType(String contentType) {
this.contentType = contentType;
}
public Long getSize() {
return size;
}
public void setSize(Long size) {
this.size = size;
}
public Date getUploadDate() {
return uploadDate;
}
public void setUploadDate(Date uploadDate) {
this.uploadDate = uploadDate;
}
public String getMd5() {
return md5;
}
public void setMd5(String md5) {
this.md5 = md5;
}
public Binary getContent() {
return content;
}
public void setContent(Binary content) {
this.content = content;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public File(String name, String contentType, Long size, Binary content) {
this.name = name;
this.contentType = contentType;
this.size = size;
this.uploadDate=new Date();
this.content = content;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
File file = (File) o;
return Objects.equals(id, file.id) &&
Objects.equals(name, file.name) &&
Objects.equals(contentType, file.contentType) &&
Objects.equals(size, file.size) &&
Objects.equals(uploadDate, file.uploadDate) &&
Objects.equals(md5, file.md5) &&
Objects.equals(content, file.content) &&
Objects.equals(path, file.path);
}
@Override
public int hashCode() {
return Objects.hash(id, name, contentType, size, uploadDate, md5, content, path);
}
@Override
public String toString() {
return "File{" +
"id='" + id + '\'' +
", name='" + name + '\'' +
", contentType='" + contentType + '\'' +
", size=" + size +
", uploadDate=" + uploadDate +
", md5='" + md5 + '\'' +
", content=" + content +
", path='" + path + '\'' +
'}';
}
}
package com.lijun.spring.boot.repository;
import com.lijun.spring.boot.domain.File;
import org.springframework.data.mongodb.repository.MongoRepository;
public interface FileRepository extends MongoRepository<File,String> {
}
package com.lijun.spring.boot.service;
import com.lijun.spring.boot.domain.File;
import java.util.List;
import java.util.Optional;
public interface FileService {
/*
* 保存文件
* */
File saveFile(File file);
/*
* 批量保存文件
* */
List<File> saveFiles(List<File> uploadFiles);
/*
* 删除文件
* */
void removeFile(String id);
/*
* 根据id获取文件
* */
Optional<File> getFileById(String id);
/*
* 分页查询,按上传时间降序
* */
List<File> listFileByPage(int pageIndex,int pageSize);
}
package com.lijun.spring.boot.service;
import com.lijun.spring.boot.domain.File;
import com.lijun.spring.boot.repository.FileRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import java.util.*;
@Service
public class FileServiceImpl implements FileService {
@Autowired
private FileRepository fileRepository;
@Override
public File saveFile(File file) {
return fileRepository.save(file);
}
@Override
public List<File> saveFiles(List<File> uploadFiles) {
return fileRepository.saveAll(uploadFiles);
}
@Override
public void removeFile(String id) {
fileRepository.deleteById(id);
}
@Override
public Optional<File> getFileById(String id) {
return fileRepository.findById(id);
}
@Override
public List<File> listFileByPage(int pageIndex, int pageSize) {
Sort sort = Sort.by(Sort.Direction.DESC, "uploadDate");
Pageable pageable = PageRequest.of(pageIndex, pageSize, sort);
Page<File> page = fileRepository.findAll(pageable);
List<File> list = page.getContent();
return list;
}
}
package com.lijun.spring.boot.controller;
import com.alibaba.fastjson.JSON;
import com.lijun.spring.boot.domain.File;
import com.lijun.spring.boot.service.FileService;
import com.lijun.spring.boot.util.MD5Util;
import org.bson.types.Binary;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
@CrossOrigin(origins = "*",maxAge = 3600) //允许所有域名访问
@Controller
@RequestMapping("/files")
public class FileController {
@Autowired
private FileService fileService;
@Value("${server.address}")
private String serverAddress;
@Value("${server.port}")
private String serverPort;
/*
* 显示最新二十条数据
* */
@GetMapping
public String index(Model model,@RequestParam(value="async",required=false) boolean async){
List<File> files = fileService.listFileByPage(0, 20);
model.addAttribute("files",files);
if(async==true){
return "index :: #fileTable";
}
return "index";
}
/*
* 分页查询文件
* */
@GetMapping("/{pageIndex}/{pageSize}")
@ResponseBody
public List<File> listFileByPage(@PathVariable int pageIndex,@PathVariable int pageSize){
return fileService.listFileByPage(pageIndex, pageSize);
}
/*
* 获取文件片信息
* Content-Disposition 响应标头是指示内容是否预期在浏览器中内联显示的标题,即,作为网页或作为网页的一部分或作为附件下载并且本地保存。
* 如果使下载文件的话,语法就是"attachment(附件)":"fileName"=value
* attachment(表示它应该下载;大多数浏览器呈现“另存为”对话框,预先填入filename如果存在参数的值)
*
* application/octet-stream 只能提交二进制,而且只能提交一个二进制,如果提交文件的话,只能提交一个文件,后台接收参数只能有一个,而且只能是流(或者字节数组)
* ( 二进制流,不知道下载文件类型),例如前端下载图片我们不知道图片的后缀是jpg或jpeg或icon就可以用这个
* */
@GetMapping("/{id}")
@ResponseBody
public ResponseEntity<Object> FileMessage(@PathVariable String id) throws UnsupportedEncodingException {
Optional<File> file = fileService.getFileById(id); //自定义查找图片,这个根据个人来实现
if(file.isPresent()){
/*这里才是核心的部分*/
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment;fileName=\""+new String(file.get().getName().getBytes("utf-8"),"ISO-8859-1")+"\"")
// .header(HttpHeaders.CONTENT_TYPE, "application/octet-stream")
.header(HttpHeaders.CONTENT_TYPE, file.get().getContentType())
.header(HttpHeaders.CONTENT_LENGTH, file.get().getSize()+"")
.header(HttpHeaders.CONNECTION, "close")
.body(file.get().getContent().getData());
}else {
return ResponseEntity.status(HttpStatus.NOT_FOUND).body("file was not found");
}
}
/*
* 在线显示文件
* CONTENT_DISPOSITION这个可以不写,返回去的就是没有文件名而已
* HttpHeaders.CONTENT_TYPE这个要写,不然返回去浏览器解析不出这是个图片
* */
@GetMapping("/view/{id}")
public ResponseEntity<Object> serveFileOnline(@PathVariable String id){
Optional<File> file = fileService.getFileById(id);
if(file.isPresent()){
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION, "fileName=\""+file.get().getName()+"\"")
.header(HttpHeaders.CONTENT_TYPE, file.get().getContentType())
.header(HttpHeaders.CONTENT_LENGTH, file.get().getSize()+"")
.header(HttpHeaders.CONNECTION, "close")
.body(file.get().getContent().getData());
}else{
return ResponseEntity.status(HttpStatus.NOT_FOUND).body("file was not found");
}
}
/*
* 上传
* RedirectAttributes 是Spring mvc 3.1版本之后出来的一个功能,专门用于重定向之后还能带参数跳转的的工具类
* */
@PostMapping
public String handleFileUpload(@RequestParam("file")MultipartFile file, RedirectAttributes redirectAttributes){
try{
File f = new File(file.getOriginalFilename(), file.getContentType()
, file.getSize(), new Binary(file.getBytes()));
f.setMd5(MD5Util.getMD5(file.getInputStream()));
fileService.saveFile(f);
} catch (IOException | NoSuchAlgorithmException e) {
e.printStackTrace();
redirectAttributes.addFlashAttribute("mesasge","Your "+file.getOriginalFilename()+"is wrong"); //; 这种方法是隐藏了参数,链接地址上不直接暴露
return "redirect:/files";
}
// redirectAttributes.addFlashAttribute("message", "You successfully upload "+file.getOriginalFilename()+"!");
redirectAttributes.addFlashAttribute("message", "成功上传文件 "+file.getOriginalFilename()+"!");
return "redirect:/files";
}
/*
* 批量上传
* */
@PostMapping("/uploadFiles")
public String handleFilesUpload(@RequestParam("file")MultipartFile files[], RedirectAttributes redirectAttributes){
ArrayList<MultipartFile> list=new ArrayList<>(Arrays.asList(files));
try{
ArrayList<File> uploadFiles=new ArrayList<>();
for (MultipartFile file: list) {
File f=new File(file.getOriginalFilename(), file.getContentType()
, file.getSize(), new Binary(file.getBytes()));
f.setMd5(MD5Util.getMD5(file.getInputStream()));
uploadFiles.add(f);
}
fileService.saveFiles(uploadFiles);
} catch (IOException | NoSuchAlgorithmException e) {
e.printStackTrace();
redirectAttributes.addFlashAttribute("mesasge","批量上传失败"); //; 这种方法是隐藏了参数,链接地址上不直接暴露
return "redirect:/files";
}
redirectAttributes.addFlashAttribute("message", "成功上传 "+list.size()+"个文件!");
return "redirect:/files?async=true";
}
/*
* 上传接口
* */
@PostMapping("/upload")
@ResponseBody
public ResponseEntity<String> handleFileUpload(@RequestParam("file") MultipartFile file,@RequestParam("username") String username){
try{
// File f=new File(file.getOriginalFilename(),file.getContentType()
// ,file.getSize(),new Binary(file.getBytes()));
File f=new File(file.getOriginalFilename()+"_"+username,file.getContentType()
,file.getSize(),new Binary(file.getBytes()));
f.setMd5(MD5Util.getMD5(file.getInputStream()));
File returnFile=fileService.saveFile(f);
String path="//"+serverAddress+":"+serverPort+"/files/view/"+returnFile.getId();
System.out.println(path);
return ResponseEntity.status(HttpStatus.OK).body(path);
}catch (IOException | NoSuchAlgorithmException e){
e.printStackTrace();
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(e.getMessage());
}
}
/*编辑博客的上传接口*/
@PostMapping("/blogUpload/{username}")
@ResponseBody
public ResponseEntity<String> blogUpload(@RequestParam("file") MultipartFile file,@PathVariable(value = "username") String username){
try{
// File f=new File(file.getOriginalFilename(),file.getContentType()
// ,file.getSize(),new Binary(file.getBytes()));
File f=new File(username+'_'+file.getOriginalFilename(),file.getContentType()
,file.getSize(),new Binary(file.getBytes()));
f.setMd5(MD5Util.getMD5(file.getInputStream()));
File returnFile=fileService.saveFile(f);
String path="//"+serverAddress+":"+serverPort+"/files/view/"+returnFile.getId();
System.out.println(path);
return ResponseEntity.status(HttpStatus.OK).body(path);
}catch (IOException | NoSuchAlgorithmException e){
e.printStackTrace();
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(e.getMessage());
}
}
/*
* 批量上传接口
* */
@PostMapping("/uploads")
@ResponseBody
public ResponseEntity<String> handleFileUploads(@RequestParam("file")MultipartFile files[]){
ArrayList<MultipartFile> list=new ArrayList<>(Arrays.asList(files));
try{
ArrayList<File> uploadFiles=new ArrayList<>();
for (MultipartFile file: list) {
File f=new File(file.getOriginalFilename(), file.getContentType()
, file.getSize(), new Binary(file.getBytes()));
f.setMd5(MD5Util.getMD5(file.getInputStream()));
uploadFiles.add(f);
}
List<File> returnFiles=fileService.saveFiles(uploadFiles);
ArrayList<String> urlList=new ArrayList<>();
for (File f: returnFiles) {
urlList.add("//"+serverAddress+":"+serverPort+"/files/view/"+f.getId());
}
String urls = JSON.toJSONString(urlList);
System.out.println(urls);
return ResponseEntity.status(HttpStatus.OK).body(urls);
}catch (IOException | NoSuchAlgorithmException e){
e.printStackTrace();
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(e.getMessage());
}
}
/*
* 删除文件
* */
@DeleteMapping("/{id}")
@ResponseBody
public ResponseEntity<String> deleteFile(@PathVariable String id){
try{
fileService.removeFile(id);
return ResponseEntity.status(HttpStatus.OK).body("delete_success");
}catch (Exception e){
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(e.getMessage());
}
}
}
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
<!--<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongodb-driver-sync</artifactId>
<version>4.0.0-beta1</version>
</dependency>
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
</dependency>-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.41</version>
</dependency>
</dependencies>